MCP PDF Server
README.md
# π MCP PDF Server
An **MCP (Model Context Protocol)** server that lets AI assistants **query your PDF documents**. Drop your PDFs, ingest them into a vector database, and ask questions β answers are grounded in your actual documents.
---
## β¨ Features
- **π MCP-Compatible** β Works with any MCP client (GitHub Copilot, Antigravity, etc.)
- **π Auto PDF Discovery** β Automatically finds, extracts, chunks, and embeds all PDFs in your folder
- **π Vector Search** β Retrieves the most relevant passages before generating answers
- **π³ Docker-Ready** β Runs as a containerized server with one command
- **ποΈ Qdrant** β Fast, open-source vector database for similarity search
---
## ποΈ How It Works
```
βββββββββββββββ MCP (stdio) βββββββββββββββββββββ HTTP ββββββββββββ
β AI Assistant ββββββββββββββββββββββΊβ MCP PDF Server βββββββββββββββΊβ Qdrant β
β β β β β Vector DBβ
βββββββββββββββ β 1. Embed question β ββββββββββββ
β 2. Search vectors β
β 3. Generate answerβ LLM API
β βββββββββββββββΊ
βββββββββββββββββββββ (Embeddings
+ Generation)
```
1. You ask a question via your AI assistant.
2. The server **embeds** the question using your choice of embedding model.
3. It **searches** Qdrant for the top 5 most relevant text chunks from your PDFs.
4. It **generates** an answer using an LLM, grounded in the retrieved context.
---
## π Quick Start
### Prerequisites
- [Docker & Docker Compose](https://docs.docker.com/get-docker/)
- [Node.js 20+](https://nodejs.org/) (for ingestion only)
- [LLM API Key]
### 1. Clone & Configure
```bash
git clone https://github.com/your-username/mcp-pdf-server.git
cd mcp-pdf-server
cp .env.example .env
```
Edit `.env` and set your API key:
```env
API_KEY=nvapi-your_key_here
```
### 2. Start Qdrant
```bash
docker-compose up -d
```
### 3. Add Your PDFs & Ingest
Place your PDF documents in the `pdfs/` folder, then:
```bash
npm install # first time only
npm run ingest
```
All PDFs in the folder are automatically discovered and ingested.
### 4. Build the Server Image
```bash
docker build -t mcp-pdf-server .
```
### 5. Connect to Your AI Assistant
Add to your AI assistant's MCP config (e.g., `mcp_config.json`):
```json
{
"mcpServers": {
"pdf-docs": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--network",
"mcp-network",
"-e",
"API_KEY",
"-e",
"QDRANT_URL=http://mcp-qdrant:6333",
"-e",
"COLLECTION_NAME=documents",
"-e",
"EMBED_MODEL=nvidia/nv-embedqa-e5-v5",
"-e",
"GEN_MODEL=qwen/qwen2.5-coder-32b-instruct",
"mcp-pdf-server"
],
"env": {
"API_KEY": "your_nvapi_key_here"
}
}
}
}
```
**Done!** Ask your AI assistant any question about your documents.
---
## π§ Available Tools
| Tool | Description |
| --------------- | -------------------------------------------------------------------------------------------------------- |
| `ask_documents` | Ask any question. The server retrieves relevant context from your ingested PDFs and generates an answer. |
---
## βοΈ Environment Variables
| Variable | Description | Default |
| ------------------- | ----------------------------- | --------------------------------- |
| `API_KEY` | LLM API key | _(required)_ |
| `EMBED_MODEL` | Embedding model | `nvidia/nv-embedqa-e5-v5` |
| `GEN_MODEL` | Generation model | `qwen/qwen2.5-coder-32b-instruct` |
| `COLLECTION_NAME` | Qdrant collection name | `documents` |
| `QDRANT_URL` | Qdrant connection URL | `http://localhost:6333` |
| `EMBED_BATCH_SIZE` | Chunks per embedding batch | `15` |
| `EMBED_MAX_RETRIES` | Max retries on API failure | `3` |
| `EMBED_COOLOFF_MS` | Cooldown between batches (ms) | `500` |
> **Note:** The `.env` file is used for local ingestion. The `mcp_config.json` passes env vars via Docker `-e` flags for the server.
---
## π Project Structure
```
mcp-pdf-server/
βββ pdfs/ # Place your PDF documents here
βββ src/
β βββ server.ts # MCP server entry point
β βββ llm/
β β βββ provider.ts # LLM API client (embed + generate)
β βββ vector/
β β βββ qdrant.ts # Qdrant client config
β βββ ingest/
β βββ main.ts # Ingestion orchestrator (auto-discovers PDFs)
β βββ extract.ts # PDF text extraction
β βββ chunk.ts # Text chunking
β βββ embed.ts # Batch embedding & Qdrant insertion
βββ docker-compose.yml # Qdrant service
βββ Dockerfile # Server image
βββ .env.example # Env var template (safe to commit)
βββ .gitignore # Keeps secrets & binaries out of git
βββ package.json
```
---
## π οΈ Development
For local development with hot-reloading:
```bash
npm install
docker-compose up -d # Start Qdrant
npm run dev # Server with hot-reload
```
To use the local dev server with your AI assistant, change `mcp_config.json` to:
```json
{
"mcpServers": {
"pdf-docs": {
"command": "npx",
"args": ["tsx", "src/server.ts"],
"cwd": "/path/to/mcp-pdf-server",
"env": {
"API_KEY": "your_nvapi_key_here",
"QDRANT_URL": "http://localhost:6333",
"COLLECTION_NAME": "documents",
"EMBED_MODEL": "nvidia/nv-embedqa-e5-v5",
"GEN_MODEL": "qwen/qwen2.5-coder-32b-instruct"
}
}
}
}
```
---
## π Use Cases
This server works with **any** PDF knowledge base:
- π Technical books β Architecture, algorithms, system design
- π Company docs β Wikis, runbooks, policies
- π Research papers β Academic papers, whitepapers
- π Legal documents β Contracts, compliance
- π Course material β Textbooks, lecture notes
---
## π Troubleshooting
| Problem | Solution |
| ------------------------- | -------------------------------------------------------------------- |
| Server can't reach Qdrant | `docker ps` β Ensure `mcp-qdrant` is running on `mcp-network` |
| Embeddings mismatch | Changed `EMBED_MODEL`? Delete `qdrant_storage/` and re-ingest |
| Rebuild server image | `docker build -t mcp-pdf-server .` after code changes |
| Reset all data | Delete `./qdrant_storage/` and re-run `npm run ingest` |
| Rate limiting | Increase `EMBED_COOLOFF_MS` or decrease `EMBED_BATCH_SIZE` in `.env` |
| No PDFs found | Ensure `.pdf` files are placed in the `pdfs/` directory |
---
## π License
ISC
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues