MCP server for retrieving context from a Qdrant vector database
Project description
MADPANDA3D QDRANT MCP
Manage your Vector Database how you see fit
MADPANDA3D QDRANT MCP is a production-ready Model Context Protocol server for Qdrant. It turns your vector store into a managed memory layer with structured controls for ingest, retrieval, validation, and ongoing cleanup.
Use it to keep memories clean, deduped, and relevance-tuned over time. The toolkit includes safe dry-run previews, bulk maintenance jobs with progress reporting, and operational guardrails so agents can manage your database at scale without chaos.
Overview
This server is designed for production workloads and supports hosted header-auth access for clients like n8n, Claude Desktop, and other MCP-capable agents.
Hosted MCP (Header Auth)
Use the MADPANDA3D hosted endpoint:
https://qdrant-mcp.madpanda3d.com/mcp
Note: https://qdrant-mcp.madpanda3d.com/mcp/ is deprecated and returns 410 Gone with a migration message.
n8n setup:
- Add MCP tool node to your agent.
- Add the MCP endpoint URL.
- Set Server transport to HTTP streamable.
- Set Auth to Multiple Headers Auth.
- Add headers:
X-MADPANDA-PORTAL-GRANTX-Qdrant-UrlX-Qdrant-Api-KeyX-Collection-Name(optional)X-Embedding-Provider(optional; required for semantic search + write tools)X-Embedding-Model(optional; required withX-Embedding-Provider)X-OpenAI-Api-Key(required whenX-Embedding-Provider=openai)
- Save the auth credentials.
- Set Tools to include → All.
n8n Setup
Screenshots below show the MCP node configuration in n8n.
Deploy
Quickstart
Install (pip)
pip install mad-mcp-qdrant
Run with Docker
docker build -t mcp-server-qdrant .
docker run -d --name mcp-qdrant \
--restart unless-stopped \
--network mcp-network \
--env-file .env \
mcp-server-qdrant
Or use the hosted-standard compose file:
cp .env.example .env
docker compose up -d --build
Auto-update with Watchtower (GHCR)
# Run from GHCR (make the package public or login to GHCR first).
docker run -d --name mcp-qdrant \
--network mcp-network \
--env-file .env \
--label com.centurylinklabs.watchtower.enable=true \
ghcr.io/<owner>/mad-mcp-qdrant:latest \
mcp-server-qdrant --transport streamable-http
# Watchtower will pull new release images and restart the container.
docker run -d --name watchtower \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower \
--cleanup --interval 1800 --label-enable
Run locally (uvx)
QDRANT_URL=... COLLECTION_NAME=... uvx mad-mcp-qdrant
Prefer mad-mcp-qdrant; mcp-server-qdrant remains as a compatible alias.
Tools
Most mutating tools support dry_run + confirm and return a dry_run_diff preview for safer approvals.
Search tools are token-safe by default. qdrant-find,
qdrant-find-short-term, and qdrant-recommend-memories return compact
results unless response_mode="payload" is requested. Start with top_k=3-5,
add filters when possible, and increase detail only after selecting a specific
result. Use metadata_fields, group_by_doc, max_chunks_per_doc,
min_score, and max_output_chars when an agent needs tighter result shaping.
For second-brain workflows, prefer qdrant-build-context: it returns a compact,
cited context pack with a response budget, document dedupe, optional filters, and
a safe relax-filters fallback before an agent spends more calls. For large
content, prefer qdrant-ingest-document or qdrant-ingest-textbook instead of
sending long text directly to store tools. For school work, qdrant-study-search
remains a convenience profile for the MCP_STUDY_COLLECTION collection.
Core Memory Tools
qdrant-store: store a single memory point with metadata.qdrant-cache-memory: store short-term memory with a TTL in a cache collection.qdrant-promote-short-term: promote short-term memories into the long-term collection.qdrant-ingest-with-validation: validate inputs, optionally quarantine, then store.qdrant-ingest-document: chunk a document and store as multiple points.- PDF ingestion runs native text extraction plus OCR by default (
ocr=true). - OCR is local (Tesseract via
pytesseract+pdf2image), not a third-party API.
- PDF ingestion runs native text extraction plus OCR by default (
qdrant-ingest-textbook: submit an async textbook PDF ingestion job (source_url-only).- Returns immediately with
job_idfor large-file workflows. - Requires metadata:
class,material_type,title,author,edition,isbn. - Uses streaming download + page-wise extraction to reduce memory pressure.
- With
ocr=true, applies OCR coverage-gating (blank/low-text pages first) and fails fast if target coverage cannot be met within budget. - Job status is persisted on disk so restart scenarios return structured failure instead of
Job not found.
- Returns immediately with
qdrant-build-context: build a collection-agnostic, token-budgeted context pack with cited snippets, document/source dedupe, optional exact filters, and relax-filters fallback.qdrant-study-search: search school/study materials with compact output and direct course/week/module/material filters.qdrant-find: query vectors with filters and return matches.qdrant-find-short-term: query the short-term memory cache collection.qdrant-recommend-memories: recommend memories using positive/negative examples.qdrant-update-point: update payload fields for a point id.qdrant-patch-payload: patch specific payload keys for a point id.qdrant-tag-memories: append or replace labels for a set of points.qdrant-link-memories: link memories via related ids and optional associations.qdrant-list-points: scroll point ids in a collection with filters.qdrant-get-points: fetch points by id list with payload/vectors.qdrant-count-points: count points that match optional filters.
Agent Navigation
qdrant-check-configuration: check hosted readiness, accepted headers, cache settings, and missing configuration without returning secrets.qdrant-list-capabilities: list compact capability groups and common workflows.qdrant-get-endpoint-coverage: summarize Qdrant endpoint coverage and documented exclusions fromdocs/endpoint-coverage.md.qdrant-get-tool-usage: inspect a tool schema, annotations, and token-safe usage guidance.qdrant-describe-collection: summarize collection size, vectors, indexed fields, and useful retrieval tools.qdrant-summarize-collection-schema: map indexed payload fields to supportedmemory_filterkeys.qdrant-suggest-filters: sample indexed metadata values and suggest exact filters for cleaner semantic retrieval.
Housekeeping + Quality
qdrant-audit-memories: scan for missing fields, bad payloads, and duplicates.qdrant-backfill-memory-contract: populate missing metadata fields at scale.qdrant-bulk-patch: patch payloads in bulk by filter or ids (dry-run supported).qdrant-dedupe-memories: dedupe exact matches by hash.qdrant-find-near-duplicates: cluster semantic near-duplicates.qdrant-merge-duplicates: merge duplicate groups into a canonical point.qdrant-reembed-points: recompute embeddings for selected points.qdrant-expire-memories: delete/archive memories pastexpires_at_ts.qdrant-expire-short-term: delete expired memories from the short-term cache.qdrant-delete-points: delete points by id list.qdrant-delete-by-filter: delete points that match a filter.qdrant-delete-document: delete all chunks for a document id.
Jobs + Progress
qdrant-submit-job: start a background maintenance job.qdrant-get-ingest-status: ingest-focused status/metrics for textbook jobs.qdrant-cancel-ingest: cancel a running textbook ingest job.qdrant-job-status: get job status and summary.qdrant-job-progress: read progress counters and phase.qdrant-job-logs: tail recent logs for a job.qdrant-job-result: fetch the final job result.qdrant-cancel-job: cancel a running job.
Collection + Admin
qdrant-health-check: validate collection health and expected indexes.qdrant-metrics-snapshot: capture collection stats and index coverage.qdrant-ensure-payload-indexes: create missing payload indexes.qdrant-optimizer-status: report optimizer and segment status.qdrant-update-optimizer-config: update optimizer settings (admin).qdrant-list-collections: list all collections.qdrant-create-collection: create a collection with embedding-compatible vector settings and default payload indexes.qdrant-collection-exists: check if a collection exists.qdrant-collection-info: fetch collection config and metadata.qdrant-collection-stats: read collection stats (points, segments).qdrant-collection-vectors: show vector config for the collection.qdrant-collection-payload-schema: list payload schema + indexed fields.qdrant-get-vector-name: resolve the active vector name.qdrant-list-aliases: list all aliases.qdrant-collection-aliases: list aliases for a collection.qdrant-collection-cluster-info: cluster and shard info.qdrant-list-snapshots: list collection snapshots.qdrant-list-full-snapshots: list full snapshots on the server.qdrant-list-shard-snapshots: list shard snapshots for a collection.qdrant-create-snapshot: create a new collection snapshot.qdrant-restore-snapshot: restore a snapshot into a collection.
Configuration
Environment Variables
| Name | Description | Default Value |
|---|---|---|
MCP_PORTAL_GRANT_TOKEN |
Required grant token for /mcp HTTP traffic from the MAD MCP Portal |
unset |
QDRANT_URL |
URL of the Qdrant server | None |
QDRANT_API_KEY |
API key for the Qdrant server | None |
COLLECTION_NAME |
Name of the default collection to use. | None |
QDRANT_VECTOR_NAME |
Override vector name used by the MCP server | None |
QDRANT_LOCAL_PATH |
Path to the local Qdrant database (alternative to QDRANT_URL) |
None |
QDRANT_SEARCH_LIMIT |
Default result limit when top_k is omitted |
10 |
QDRANT_READ_ONLY |
Hide mutating tools when enabled | false |
QDRANT_ALLOW_ARBITRARY_FILTER |
Allow raw Qdrant filter input | false |
EMBEDDING_PROVIDER |
Embedding provider to use (fastembed or openai) |
fastembed |
EMBEDDING_MODEL |
Name of the embedding model to use | sentence-transformers/all-MiniLM-L6-v2 |
EMBEDDING_VECTOR_SIZE |
Vector size override (required for unknown OpenAI models) | unset |
EMBEDDING_VERSION |
Embedding version label stored with each memory | unset |
OPENAI_API_KEY |
OpenAI API key (required for openai provider) |
unset |
OPENAI_BASE_URL |
OpenAI-compatible base URL (optional) | unset |
OPENAI_ORG |
OpenAI organization ID (optional) | unset |
OPENAI_PROJECT |
OpenAI project ID (optional) | unset |
TOOL_STORE_DESCRIPTION |
Custom description for the store tool | See default in src/mcp_server_qdrant/settings.py |
TOOL_FIND_DESCRIPTION |
Custom description for the find tool | See default in src/mcp_server_qdrant/settings.py |
MCP_ADMIN_TOOLS_ENABLED |
Enable admin-only tools (optimizer updates) | false |
MCP_MUTATIONS_REQUIRE_ADMIN |
Require admin access for mutating tools | false |
MCP_MAX_BATCH_SIZE |
Max batch size for bulk operations | 500 |
MCP_MAX_POINT_IDS |
Max point id list size | 500 |
MCP_STRICT_PARAMS |
Reject unknown keys/filters and oversized text | false |
MCP_MAX_TEXT_LENGTH |
Max text length before chunking | 8000 |
MCP_TEXTBOOK_MAX_FILE_BYTES |
Max textbook file size (bytes) for async ingest | 104857600 |
MCP_TEXTBOOK_MAX_PAGES |
Max textbook page count for async ingest | 1000 |
MCP_TEXTBOOK_MAX_EXTRACTED_CHARS |
Max extracted characters for async textbook ingest | 3000000 |
MCP_TEXTBOOK_MAX_CHUNKS |
Max chunk count for async textbook ingest | 20000 |
MCP_TEXTBOOK_OCR_LOW_TEXT_THRESHOLD_CHARS |
Chars/page threshold considered low-text during OCR gating | 120 |
MCP_TEXTBOOK_OCR_MIN_COVERAGE_RATIO |
Minimum acceptable text coverage ratio after OCR budget pass | 0.85 |
MCP_TEXTBOOK_OCR_MAX_PAGES |
Max number of pages eligible for OCR in textbook ingest | 120 |
MCP_TEXTBOOK_OCR_MAX_PAGE_RATIO |
Max OCR page budget as ratio of total pages | 0.30 |
MCP_TEXTBOOK_JOB_TIMEOUT_SECONDS |
Timeout for async textbook ingest jobs | 2700 |
MCP_TEXTBOOK_EMBED_BATCH_SIZE |
Embed batch size for textbook jobs | 32 |
MCP_TEXTBOOK_UPSERT_BATCH_SIZE |
Upsert batch size for textbook jobs | 64 |
MCP_TEXTBOOK_MAX_CONCURRENCY |
Max concurrent textbook embed/upsert workers | 2 |
MCP_TEXTBOOK_JOB_STATE_DIR |
Local directory used to persist async textbook job state | /tmp/mcp-server-qdrant/jobs |
MCP_TEXTBOOK_JOB_STATE_RETENTION_HOURS |
Retention window for terminal persisted job state | 168 |
MCP_QUERY_EMBEDDING_CACHE_SIZE |
Max cached query embeddings; set 0 to disable |
256 |
MCP_QUERY_EMBEDDING_CACHE_TTL_SECONDS |
Query embedding cache TTL seconds | 3600 |
MCP_DEDUPE_ACTION |
Dedupe behavior (update or skip) |
update |
MCP_INGEST_VALIDATION_MODE |
Validation mode (allow, reject, quarantine) |
allow |
MCP_QUARANTINE_COLLECTION |
Collection name for quarantined memories | jarvis-quarantine |
MCP_HEALTH_CHECK_COLLECTION |
Default collection for health check | unset |
MCP_SHORT_TERM_COLLECTION |
Collection name for short-term memory cache | jarvis-short-term |
MCP_STUDY_COLLECTION |
Default collection for qdrant-study-search |
school |
MCP_SHORT_TERM_TTL_DAYS |
Default TTL (days) for short-term memory cache | 7 |
MCP_SERVER_VERSION |
Optional git SHA for telemetry | unset |
MCP_ALLOW_REQUEST_OVERRIDES |
Allow per-request Qdrant headers | false |
MCP_REQUIRE_REQUEST_QDRANT_URL |
Require X-Qdrant-Url when overrides enabled |
true |
MCP_REQUIRE_REQUEST_QDRANT_API_KEY |
Require X-Qdrant-Api-Key when overrides enabled |
false |
MCP_REQUIRE_REQUEST_COLLECTION |
Require X-Collection-Name when overrides enabled |
true |
MCP_DISABLE_DEFAULT_QDRANT_FALLBACK |
Disable server-side Qdrant fallback defaults | false |
MCP_DISABLE_DEFAULT_EMBEDDING_FALLBACK |
Require embedding headers for all tools | false |
MCP_PORTAL_GRANT_HEADER |
Header name for the MAD MCP Portal grant token | x-madpanda-portal-grant |
MCP_QDRANT_URL_HEADER |
Header name for Qdrant URL | x-qdrant-url |
MCP_QDRANT_API_KEY_HEADER |
Header name for Qdrant API key | x-qdrant-api-key |
MCP_COLLECTION_NAME_HEADER |
Header name for collection name | x-collection-name |
MCP_QDRANT_VECTOR_NAME_HEADER |
Header name for vector name | x-qdrant-vector-name |
MCP_EMBEDDING_PROVIDER_HEADER |
Header name for embedding provider | x-embedding-provider |
MCP_EMBEDDING_MODEL_HEADER |
Header name for embedding model | x-embedding-model |
MCP_EMBEDDING_VECTOR_SIZE_HEADER |
Header name for embedding vector size | x-embedding-vector-size |
MCP_OPENAI_API_KEY_HEADER |
Header name for OpenAI API key | x-openai-api-key |
MCP_OPENAI_BASE_URL_HEADER |
Header name for OpenAI-compatible base URL | x-openai-base-url |
MCP_OPENAI_ORG_HEADER |
Header name for OpenAI organization | x-openai-org |
MCP_OPENAI_PROJECT_HEADER |
Header name for OpenAI project | x-openai-project |
MCP_QDRANT_HOST_ALLOWLIST |
Comma/space-separated allowed Qdrant hostnames | unset |
Note: You cannot provide both QDRANT_URL and QDRANT_LOCAL_PATH at the same time.
Example .env templates
Base (Qdrant + hosted overrides):
MCP_PORTAL_GRANT_TOKEN=replace-with-shared-portal-token
QDRANT_URL=https://your-qdrant-host:6333
QDRANT_API_KEY=your-qdrant-api-key
COLLECTION_NAME=
# Hosted MCP: require client headers (recommended for public endpoints)
MCP_ALLOW_REQUEST_OVERRIDES=true
MCP_REQUIRE_REQUEST_QDRANT_URL=true
MCP_REQUIRE_REQUEST_QDRANT_API_KEY=true
MCP_REQUIRE_REQUEST_COLLECTION=false
MCP_DISABLE_DEFAULT_QDRANT_FALLBACK=true
MCP_DISABLE_DEFAULT_EMBEDDING_FALLBACK=false
MCP_QDRANT_HOST_ALLOWLIST=*.qdrant.io
MCP_QUERY_EMBEDDING_CACHE_SIZE=256
MCP_QUERY_EMBEDDING_CACHE_TTL_SECONDS=3600
FastEmbed (local embeddings, no external API):
EMBEDDING_PROVIDER=fastembed
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
OpenAI embeddings:
EMBEDDING_PROVIDER=openai
EMBEDDING_MODEL=text-embedding-3-large
OPENAI_API_KEY=your-openai-key
OpenAI-compatible embeddings (custom base URL):
EMBEDDING_PROVIDER=openai
EMBEDDING_MODEL=your-model-id
OPENAI_API_KEY=your-openai-compatible-key
OPENAI_BASE_URL=https://your-openai-compatible-host/v1
# Optional:
OPENAI_ORG=
OPENAI_PROJECT=
Hosted MCP (Bring Your Own Qdrant)
If you run a public MCP endpoint and want users to supply their own Qdrant credentials (e.g., in n8n), enable per-request overrides and send headers.
Server env:
MCP_PORTAL_GRANT_TOKEN=replace-with-shared-portal-token
MCP_ALLOW_REQUEST_OVERRIDES=true
MCP_REQUIRE_REQUEST_QDRANT_URL=true
MCP_REQUIRE_REQUEST_QDRANT_API_KEY=true
MCP_REQUIRE_REQUEST_COLLECTION=false
MCP_DISABLE_DEFAULT_QDRANT_FALLBACK=true
MCP_DISABLE_DEFAULT_EMBEDDING_FALLBACK=false
# Optional hardening
MCP_QDRANT_HOST_ALLOWLIST=*.qdrant.io
Client headers (n8n MCP node):
X-MADPANDA-PORTAL-GRANT: shared portal grant token (required for/mcp)X-Qdrant-Url: user Qdrant URL (required)X-Qdrant-Api-Key: user Qdrant API key (required in strict hosted mode)X-Collection-Name: user collection (optional; omit to work across collections)X-Qdrant-Vector-Name: optional vector name overrideX-Embedding-Provider: optional (fastembedoropenai)X-Embedding-Model: optional; required when provider is setX-Embedding-Vector-Size: optional vector size overrideX-OpenAI-Api-Key: required when provider isopenaiX-OpenAI-Base-Url: optional OpenAI-compatible endpointX-OpenAI-Org: optional OpenAI orgX-OpenAI-Project: optional OpenAI project
Behavior in hosted mode:
/healthis public and secret-free./mcpfails closed before request override, Qdrant, or embedding headers are processed whenMCP_PORTAL_GRANT_TOKENis missing orX-MADPANDA-PORTAL-GRANTis absent/invalid.- Missing embedding headers puts the session into read-only mode.
- Write/mutation tools are blocked until embedding headers are provided.
- Semantic search tools (
qdrant-find,qdrant-find-short-term) require embedding headers. - Collection-scoped tools remain visible in
tools/listand include the marker[Requires collection name]. - You can create collections without
X-Collection-Nameby callingqdrant-create-collectionwithcollection_namein tool args. - Send headers on
initialize, then reusemcp-session-idfortools/listandtools/call.
Tip: If you enable request overrides for a public endpoint, do not rely on
server-side QDRANT_* defaults. Require user headers and keep your own
Qdrant instance network-restricted.
Memory Contract
Stored memories are normalized to include at least:
text, type, entities, source, created_at, updated_at, scope, confidence, and text_hash.
Optional fields include expires_at / ttl_days, labels, related_ids, associations,
validation metadata (validation_status, validation_errors), merge markers
(merged_into, merged_from), plus embedding metadata
(embedding_model, embedding_dim, embedding_provider, embedding_version).
Document ingestion stores additional fields such as doc_id, doc_title, doc_hash,
source_url, file_name, file_type, page_start, page_end, and section_heading.
When a duplicate text_hash is found in the same scope, the server updates
last_seen_at and reinforcement_count instead of inserting a duplicate.
Maintenance Playbooks
See docs/MAINTENANCE_PLAYBOOKS.md for recommended maintenance flows.
Release & Versioning
This repo uses conventional commits and semantic-release. Every push to main runs the
release workflow, and a release is created only when commit messages warrant a version bump.
License
Apache-2.0.
Support
Affiliate Links
Services I use (affiliate)
Using these links helps support continued development.
Hostinger VPS
Cloud Hosting
Web Hosting
Website Builder
Agency Hosting
Reach
Contact
Open an issue in MADPANDA3D/QDRANT-MCP.
MADPANDA3D
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mad_mcp_qdrant-1.9.2.tar.gz.
File metadata
- Download URL: mad_mcp_qdrant-1.9.2.tar.gz
- Upload date:
- Size: 1.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fbbd71445e9e95dbeb39a7005bb044e0a1628a0a56f16e3b519f66d4bca1de6f
|
|
| MD5 |
be1783ee5a4cc57bfebca5ca8214436a
|
|
| BLAKE2b-256 |
6ef4c800d9d240f8058fb3af3e23a8da7d1e8bf30952f812e6859aaac184807f
|
File details
Details for the file mad_mcp_qdrant-1.9.2-py3-none-any.whl.
File metadata
- Download URL: mad_mcp_qdrant-1.9.2-py3-none-any.whl
- Upload date:
- Size: 104.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8babc6d649d0eb8dd4aba5d0e5e35a8f39ee80bd3afb1812dd13b63309a978fd
|
|
| MD5 |
4398dba6177c7dacb688f593f808cee9
|
|
| BLAKE2b-256 |
aa1bf53ff81443829287b23357f3f2606c515de1bbab4f107bed6ce5f894bf41
|