Nexla MCP Document Q&A Server
Enables querying PDF documents using natural language with grounded answers and source citations via a local RAG pipeline.
README
Nexla Technical Assignment: MCP Document Q&A Server
This repository contains my implementation of a Model Context Protocol (MCP) server designed to provide document intelligence over PDF files. The server allows an AI client (such as Claude Desktop or the MCP Inspector) to query unstructured PDF documents and retrieve grounded answers with source citations.
I built the system using a local-first Python stack. All PDF parsing, vector search, and LLM inference run entirely on-device with zero external API calls.
1. System Design and Component Choices
When designing this system, I focused on creating a clean, modular pipeline with a clear separation of concerns between ingestion, retrieval, prompt orchestration, and tool exposure.
+-------------------+
| MCP Client |
| (Claude Desktop) |
+---------+---------+
| stdio / JSON-RPC
+---------v---------+
| MCP Server |
| (src/server.py) |
+----+---------+----+
| |
+-----------------+ +-----------------+
| |
+--------v---------+ +---------v---------+
| Vector Retriever | | Active Metadata |
| (ChromaDB + | | Engine |
| MiniLM-L6-v2) | | (Nexset Profile) |
+--------+---------+ +-------------------+
|
| Relevant Context
+--------v---------+
| RAG Generator |
| (Ollama llama3.2)|
+------------------+
Component Selection Table
| Layer | Selection | Justification |
|---|---|---|
| MCP Framework | FastMCP |
Clean Python decorators for tool registration while adhering strictly to standard MCP JSON-RPC protocol |
| PDF Extraction | PyMuPDF (fitz) |
High-speed C-backed page parsing. Benchmarked faster than pdfplumber and preserves page boundaries reliably |
| Embeddings | sentence-transformers (all-MiniLM-L6-v2) |
Generates 384-dimensional dense vectors locally on CPU with minimal latency (~90MB model size) |
| Vector Store | ChromaDB |
Persistent on-disk vector database using cosine distance metrics with zero extra server setup |
| Local LLM | Ollama (llama3.2) |
Runs locally on CPU/GPU. Setting temperature to 0.1 ensures factual responses grounded strictly in context |
2. Nexla Architecture Alignment
Nexla emphasizes metadata-driven integrations and virtualized data products called Nexsets. I structured this MCP server to reflect those core concepts:
Virtual Data Product Abstraction (Nexset Profiles)
Rather than treating PDFs as plain text strings, my ingestion pipeline computes a NexsetMetadataProfile for every document. It infers topic tags, extracts structural headings, counts words, and calculates estimated reading time.
Agents can inspect this schema using the get_nexset_schema tool before running queries.
Grounded Context Compounding
To prevent hallucinations, the generator constructs a strict system prompt. The LLM is instructed to answer questions using only the retrieved passages. If the context does not contain enough information, the model states that explicitly. Each source reference includes the document title, page number, and vector relevance score.
3. Tool Reference
The server exposes four MCP tools for AI agents:
| Tool Name | Purpose | Key Inputs | Expected Output |
|---|---|---|---|
query_documents |
Grounded Q&A over indexed PDFs | question (str), document_filter (optional str) |
Answer string + list of source citations (document, page, score) |
get_nexset_schema |
Inspect auto-generated Nexset profile | document_name (str) |
Metadata JSON with topic tags, word metrics, headings, and governance tags |
list_documents |
List index registry & statistics | None | JSON summary of indexed documents, total pages, and chunk counts |
get_document_summary |
Executive document summary | document_name (str) |
High-level summary of main topics and referenced page numbers |
4. Setup and How to Run
Requirements
- Python 3.10 or higher
- Ollama installed and running (
ollama pull llama3.2)
Installation Steps
-
Clone the repository and enter the directory:
git clone https://github.com/Bhanunikhil/MCP-Server_Nexla.git cd MCP-Server_Nexla -
Set up a virtual environment and install dependencies:
python -m venv venv source venv/bin/activate # On Windows: .\venv\Scripts\activate pip install -r requirements.txt -
Place PDF documents in the
data/folder.
Running the Server
-
Standard MCP Server (for Claude Desktop or standard clients):
python -m src.server -
Interactive Command Line Tool:
python ask.py -
MCP Web Inspector:
fastmcp dev src/server.py
5. Technical Challenges Addressed in My Implementation
When building this MCP server, I focused on solving common technical obstacles that arise when integrating unstructured enterprise PDF data with AI models. The table below outlines these challenges and the specific technical solutions I engineered in this codebase:
| Real-World Challenge | Problem Impact | Technical Solution Implemented |
|---|---|---|
| Nested Directory Hierarchies | Enterprise document drops use nested subfolders (data/dept_a/, data/0/), causing flat file parsers to miss data. |
Implemented recursive pattern discovery (data/**/*.pdf) in ingestion.py to traverse complex folder structures automatically. |
| Vector Memory Overflow on Large Files | Indexing multi-hundred page PDFs in a single call causes memory spikes and payload exceptions in vector stores. | Implemented batched upserts (batch_size = 100) combined with deterministic chunk hashing (doc_name::page::chunk) in retriever.py for memory-safe, idempotent indexing. |
| Metadata Invisibility & Token Waste | Basic RAG models treat PDFs as dumb text strings, forcing LLMs to spend expensive context tokens just to discover document structure. | Built the NexsetMetadataProfile engine and exposed get_nexset_schema in server.py, allowing AI agents to inspect structural headings, topic tags, and read metrics instantly. |
| Context Fragmentation from Naive Chunking | Slicing text at rigid character limits cuts sentences in half, causing fragmented context and degraded embedding quality. | Built a sentence-aware chunker in ingestion.py that finds period (. ) and newline (\n) boundaries before breaking text. |
6. My Workflow and Use of AI Tooling
I used AI coding tools during development to speed up repetitive tasks while staying actively involved in architecture, debugging, and system tuning.
Engineering Decisions & AI Matrix
| Task / Focus Area | AI Assistance | My Engineering Decisions & Overrides |
|---|---|---|
| Directory Discovery | Generated flat data/*.pdf search |
Modified to recursive globbing (data/**/*.pdf) to support real enterprise nested folder datasets |
| Vector Indexing | Generated unbatched collection.add() calls |
Refactored to batch upserts (batch_size = 100) with deterministic chunk IDs (doc_name::page::chunk) to prevent memory crashes |
| Metadata Engine | Defaulted to plain text chunking | Designed NexsetMetadataProfile abstraction to auto-infer topic categories, heading structures, and read metrics |
| Windows Console I/O | Hardcoded Unicode emojis in print statements | Sanitized console print statements to standard text to avoid UnicodeEncodeError on Windows cp1252 terminals |
6. Project Layout
MCP-Server_Nexla/
├── README.md # Documentation and technical overview
├── interaction_log.md # Sample Q&A interactions with source citations
├── requirements.txt # Python dependencies
├── pyproject.toml # Project packaging settings
├── .env.example # Environment configuration template
├── ask.py # CLI script for interactive testing
├── data/ # Directory containing sample PDF documents
├── src/
│ ├── config.py # Configuration loading logic
│ ├── ingestion.py # PDF text extraction, chunking, and metadata engine
│ ├── retriever.py # Embedding generation and ChromaDB vector search
│ ├── generator.py # Ollama RAG prompt handling
│ ├── tools.py # MCP tool definitions
│ └── server.py # FastMCP entry point
└── tests/
└── test_tools.py # Unit tests
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。