MCP PDF to PGVector
Ingests PDF documents into PostgreSQL (with pgvector) for semantic search and RAG pipelines.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP PDF to PGVectorIndex the PDFs in ./contracts into a collection called 'legal-docs'."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Problem
Large language models have no direct access to documents, PDFs, or private knowledge bases. Building a RAG pipeline requires stitching together PDF parsing, text chunking, embedding generation, and vector database operations — a fragile, multi-step process that every agent project reinvents.
This MCP server collapses that pipeline into a single agent-callable tool: point it at a directory of PDFs, and it handles extraction, chunking, embedding (nomic-embed-text-v2-moe, 768-dim), and storage in pgvector — ready for semantic search.
Related MCP server: MyDocsMCP
Features
Single
uv runorpip install— no project scaffolding, no boilerplate.Local embeddings — nomic-embed-text-v2-moe runs on CPU via sentence-transformers, no API keys or network calls.
Background ingestion —
index_pdfs_for_ragreturns immediately; pollcheck_indexing_progressfor updates.Idempotent resume — re-running indexes only new/changed files (SHA-256 content hash).
Per-file error isolation — one corrupt PDF never blocks the batch.
Auto HNSW index — pgvector index created after ingestion for sub-10ms similarity search.
Production stable — uses
mcp==1.28.1(stable SDK), no pre-releases.
Architecture
┌────────────────────────────────────────────────────────────┐
│ Agent (OpenCode, Claude Desktop, etc.) │
│ calls index_pdfs_for_rag(pdf_directory, collection_name) │
└─────────────────────┬──────────────────────────────────────┘
│ JSON-RPC (stdio)
┌─────────────────────▼──────────────────────────────────────┐
│ server.py — MCP Server (FastMCP v1) │
│ │
│ 1. Scan PDF directory (recursive glob) │
│ 2. Compute SHA-256 hash of each file │
│ 3. Extract text (PyMuPDF) │
│ 4. Recursive character chunking (1000/200 default) │
│ 5. Batch embed (nomic-embed-text-v2-moe, 768-dim) │
│ 6. Batch insert into pgvector (ON CONFLICT DO NOTHING) │
│ 7. Create HNSW index on completion │
└─────────────────────┬──────────────────────────────────────┘
│ asyncpg
┌─────────────────────▼──────────────────────────────────────┐
│ PostgreSQL + pgvector │
│ │
│ documents ( │
│ collection_name TEXT, ← namespace for multi-tenant │
│ file_hash TEXT, ← SHA-256 for resume/dedup │
│ file_path TEXT, ← original source │
│ chunk_index INT, ← position within file │
│ content TEXT, ← chunk text │
│ embedding vector(768), ← nomic embedding │
│ metadata JSONB, ← extensible │
│ UNIQUE(collection_name, file_hash, chunk_index) │
│ ) │
└────────────────────────────────────────────────────────────┘Quick Start — Agent (OpenCode)
Add to your opencode.json or ~/.config/opencode/opencode.json:
{
"mcp": {
"mcp-pdf-to-pgvector": {
"type": "local",
"command": ["/path/to/mcp-pdf-to-pgvector/.venv/bin/python", "server.py"],
"enabled": true
}
}
}Once configured, the agent can call:
index_pdfs_for_rag(
pdf_directory="/path/to/pdfs",
collection_name="company-policies"
)Then poll progress:
check_indexing_progress(task_id="...")Quick Start — Local Testing
Prerequisites
Python 3.10+
PostgreSQL 15+ with pgvector extension
Setup
# Clone and enter
git clone <url>
cd mcp-pdf-to-pgvector
# Create virtual environment and install dependencies
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Configure pgvector connection
cp .env.example .env
# Edit .env with your pgvector credentials
# Start the server (listens on stdio)
python server.pyTest with MCP Inspector
source .venv/bin/activate
mcp dev server.pyOpens a browser UI where you can call index_pdfs_for_rag with a PDF directory path and collection name, then monitor progress with check_indexing_progress.
Configuration
All configuration is via environment variables in .env:
Variable | Default | Description |
|
| PostgreSQL host |
|
| PostgreSQL port |
|
| Database name |
|
| Database user |
|
| Database password |
No API keys, no model configuration. Embeddings run entirely locally.
Tools
Tool | When to use |
| User wants PDFs searchable via natural language (knowledge base, RAG, Q&A). Starts background ingestion, returns |
| After |
| User wants to stop a running ingestion, or a task is stuck. |
Schema
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
collection_name TEXT NOT NULL,
file_hash TEXT NOT NULL,
file_path TEXT NOT NULL,
chunk_index INT NOT NULL,
content TEXT NOT NULL,
embedding vector(768),
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(collection_name, file_hash, chunk_index)
);
CREATE INDEX idx_documents_collection ON documents (collection_name);
-- Auto-created after ingestion:
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200)
WHERE collection_name = ?;Production Considerations
Embedding model (~1.9GB) is downloaded on first run to
~/.cache/huggingface/hub/. Subsequent runs use the cached copy.First load takes 10–30 seconds (model download + torch import). Lifespan handler pre-loads at startup.
Memory: ~2GB RSS during ingestion (model + torch). Returns to ~200MB after ingestion completes.
PostgreSQL: Ensure
max_connectionsis sufficient. The server uses a connection pool (min: 2, max: 8).Retrieval: Add a
search_indexed_contenttool to query the indexed data — the schema and HNSW index are ready for it.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Hosted MCP server: convert PDFs to clean, LLM-ready Markdown with tables, formulas and OCR.
Document-to-Markdown MCP server — convert PDF, Office and HTML into LLM-ready Markdown.
- docs2mcpOAuthcom.docs2mcp
Query your own PDFs and documents from any MCP client. Every answer cites the page it came from.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server for document ingestion and semantic search on Qdrant. Enables ingesting local documents, generating embeddings with OpenAI, and performing vector search with metadata filters.Apache 2.0
- FlicenseAqualityDmaintenanceMCP server that enables semantic search over local PDF collections using local RAG, with automatic indexing of new documents.5-
- AlicenseAqualityDmaintenanceA local-first MCP server that ingests PDFs, extracts structure, and provides semantic search and sequential navigation tools for AI clients to query and learn from documents.10MIT
- FlicenseNot gradedqualityDmaintenanceIndexes PDF documents into Qdrant and exposes semantic search as MCP tools, enabling RAG-based interactions with your documents.-