Docs RAG MCP Case Study
Document-grounded Q&A with agent tools and MCP integration
Built a production-oriented Agentic RAG platform: NestJS backend with LangChain.js, Next.js upload and chat UI, Ollama embeddings, Qdrant vector storage, and an MCP server layer so Cursor and Claude can call business tools alongside private document search.
- Role
- Agentic AI Engineer
- Timeline
- 2025 to 2026
- Team
- Solo developer
- Stack
- NestJSNext.js 15LangChain.jsOllamaQdrantTypeScriptMCP SDKDocker
The Problem
Businesses need AI that answers from their own documents, not the public internet. At the same time, developers using Cursor and Claude want a standard protocol to let assistants call internal APIs and databases safely. Keyword search and generic chatbots fail on both fronts.
- Teams store answers in PDFs, invoices, and SOPs but keyword search misses intent and context
- Generic chatbots hallucinate because they are not grounded in private company documents
- AI assistants in Cursor and Claude Desktop need a standard way to reach internal APIs and databases, not just chat
- Vector search, document ingestion, and tool calling require separate stacks that are hard to wire together
- Local or self-hosted LLM options were needed to avoid sending sensitive docs to external APIs during development
The Solution
I built Docs RAG MCP as a monorepo combining document-grounded Q&A with an MCP server layer. The NestJS backend handles PDF ingestion, Ollama embeddings, and Qdrant vector search. The Next.js frontend provides upload and chat. MCP tools wrap APIs and databases so AI clients can act, not just read.
Next.js UI (upload + chat)
|
v
NestJS API (ChatModule + AgentModule)
|
+--------+---------+
| |
v v
LangChain RAG MCP Server (stdio)
(Ollama + Qdrant) |
v
Tools / Resources / Prompts
|
+----------+----------+
| |
v v
Headless REST API SQLite DB- NestJS ChatModule: PDF upload, text splitting, Ollama embeddings, and Qdrant persistence with in-memory fallback
- RAG ask endpoint returns answers with source file attribution and context chunk count to reduce hallucinations
- Next.js 15 frontend: drag-and-drop upload page and conversational chat UI grounded in indexed content
- AgentModule scaffold for orchestrating RAG retrieval with business tools in a ReAct-style loop
- MCP server layer (tools, resources, prompts) wrapping APIs and SQLite so AI clients invoke actions safely via stdio
- Docker Compose stack for Ollama, Qdrant, API, and frontend in a reproducible local dev environment
Screenshot

Before and After
| Before | After |
|---|---|
| Invoice details buried in PDF folders; staff search filenames manually | Natural-language queries return structured invoice lists with cited PDF sources |
| ChatGPT-style answers with no proof of where information came from | Every answer lists source documents and context chunk count |
| AI IDE assistants cannot call your APIs or database | MCP tools wrap headless APIs and SQLite with Zod-validated inputs |
| RAG prototype tied to one cloud LLM vendor | Ollama + Qdrant local stack with optional OpenAI path for production |
Results
- Working MVP: upload invoice PDFs, ask questions like show invoice lists or give me details of 36259, get grounded answers with sources
- Monorepo with NestJS API on port 3000 and Next.js UI on port 3001, runnable via pnpm dev:all
- LangChain.js RAG chain with context-only prompt: if nothing relevant is found, the model says so instead of guessing
- MCP learning server documents the thin-wrapper pattern: services hold logic, tools expose it to AI clients over stdio
- Architecture ready for agent tools (inventory, support, calendar) and LangGraph orchestration in the next phase
Key Features
1. PDF ingestion pipeline
Upload invoices, policies, or SOPs via the web UI or API. PDFs are parsed, chunked with overlap, embedded, and stored in Qdrant.
2. Source-attributed answers
Chat responses cite the exact PDF files used, so users can verify invoice numbers, customer names, and policy details.
3. Local LLM stack
Ollama runs mxbai-embed-large for embeddings and llama3.2 for chat, keeping sensitive documents off third-party LLM APIs during dev.
4. Persistent vector store
Qdrant stores embeddings across restarts. MemoryVectorStore fallback keeps development unblocked when Docker is not running.
5. MCP tool bridge
Model Context Protocol server exposes tools (API calls, DB queries), read-only resources, and prompts for Cursor and Claude Desktop.
6. Agent-ready architecture
Separate Chat and Agent modules so RAG retrieval and tool orchestration can evolve into a full LangGraph agent loop.
Technical Highlights
- NestJS ChatService: init Ollama models, connect Qdrant, ingest PDFs, run createStuffDocumentsChain RAG
- POST /chat/upload, /chat/ingest, /chat/ask REST endpoints with multer file handling
- Next.js App Router: / upload page and /chat conversational interface with Tailwind CSS v4
- LangChain RecursiveCharacterTextSplitter, QdrantVectorStore, MemoryVectorStore fallback
- MCP SDK: server.tool(), resources (shop:// URIs), prompts (analyze-sales templates), stdio transport for Cursor
- pnpm workspace monorepo with shared TypeScript config and docker-compose for Ollama + Qdrant
Why Hire Me for RAG and MCP Work
- End-to-end RAG: ingestion, embeddings, vector search, and grounded chat UI
- MCP integration so AI assistants in Cursor can call your real APIs and databases
- NestJS + LangChain.js architecture designed for production agent workflows
- Local-first LLM option (Ollama) plus vector persistence (Qdrant) for sensitive docs
- Clear separation between service logic and MCP tool wrappers for safe AI access
Need document AI, RAG, or MCP integration?
I build grounded knowledge assistants and MCP servers that connect AI tools to your APIs and databases. Available on Upwork, Fiverr, or direct.