Skip to main content
Glama
Bhanunikhil

Nexla MCP Document Q&A Server

by Bhanunikhil

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


Related MCP server: PDF RAG MCP Server

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

  1. Clone the repository and enter the directory:

    git clone https://github.com/Bhanunikhil/MCP-Server_Nexla.git
    cd MCP-Server_Nexla
  2. 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
  3. 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
A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Bhanunikhil/MCP-Server_Nexla'

If you have feedback or need assistance with the MCP directory API, please join our Discord server