Qdrant MCP
PYPI · MCP-QDRANT
The full Qdrant API as 58 MCP tools: plain-text semantic/BM25/hybrid search and a search advisor.
Available components
Last scanned (1 day ago)
Scores higher than 72% of PyPI servers
Category Databases
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security100
- No malware found by supply-chain analysis.Pass
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs uv_build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 1 of 39 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency45
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 0 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability56
- AI-judged instruction clarity (good).Pass
- Context-footprint check failed: tool/resource definitions use about 4292 tokens (~330/item across 13 items; 13 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management70
- Stability observed for 21 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage71
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 0% of tool parameters carry a description.Fail
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 2 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 14 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Checks we ran (16)
- Malware scan
- Known CVEs
- Install scripts
- Dependency health
- Source repository
- Provenance
- License
- Maintenance
- Security disclosure
- Schema quality
- Stability
- Tool coverage
- Injection markers
- Destructive annotations
- Judged manipulation
- MCP protocol
Does not apply to this package (2)
- Endpoint SecurityScored on hosted endpoints only. A package has no live endpoint of its own for us to probe.
- Transport & ReachabilityScored on hosted endpoints only. A package has no live endpoint of its own for us to probe.
The score does not measure everything. What the score does not measure →
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 5 Nov 26 +16
- Tool safety: pass → unverified ▼ security
- Stability: 0.67 → unverified ▼ security
- Malware scan: unverified → pass ▲ security
- Capabilities: pass → unverified ▼ functional
- Tool coverage: 100 → unverified ▼ functional
- Schema quality: Schema quality not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet. functional
- Package version: 2.11.0 → 2.12.0 functional
- 4 Nov 26 0
- Schema quality: 245 → 330 ▼ functional
- Schema quality: 245 → 318 ▼ functional
- Package version: 2.6.0 → 2.11.0 functional
- Package version: 2.6.0 → 2.10.0 functional
- Package version: 2.6.0 → 2.9.0 functional
- 3 Nov 26 −20
- Malware scan: pass → unverified ▼ security
- Stability: pass → 0.63 functional
- 31 Oct 26 +15
- Malware scan: unverified → pass ▲ security
- 30 Oct 26 −15
- Malware scan: pass → unverified ▼ security
- 29 Oct 26 0
- Package version: 1.0.1 → 2.6.0 functional
- 28 Oct 26 0
- Stability: 0.97 → pass security
- 27 Oct 26 0
- Stability: pass → 0.97 functional
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Analysed pypi/mcp-qdrant@2.12.0
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | pypi |
| Reason | No attestation published |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | Known build tool | uv_build |
Background: Why install scripts are a supply-chain risk →
Dependencies 39 packages
| Packages resolved | 39 |
|---|---|
| No linked repository | 1 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
qdrant_collection_create Create Qdrant collection ~674
Create a collection: a single unnamed vector (`vector_size` + `distance`), one or more named vectors (`vectors`, each a full `VectorParams` — size, distance, and optionally its own `multivector_config` for ColBERT-style multi-vectors or `quantization_config`), or a text collection (`text_model`) — exactly one of the three. `sparse_vectors` defines sparse (keyword-style) vectors at creation time. Text: `text_model` (a fastembed model, e.g. `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2`, 384 dims, multilingual, downloaded on first use) creates a `dense` Cosine vector of the model's size and records the model in the collection's metadata, so `text` in `qdrant_points_upsert` and `query_text` in `qdrant_query` embed with it. `text_language` (e.g. "spanish") adds a BM25 index on `text_field` (default `text`) for `bm25_query`: stemmed, accent-folded, stopwords removed where Qdrant has a list for the language (all but armenian and tamil); given alone, it makes a keyword-only collection with no vectors. The embedded local mode (QDRANT_LOCAL_PATH) can't rank such an index — BM25 there needs the default tokenization. `quantization_config` (scalar/product/binary) and `strict_mode_config` apply to the whole collection. `hnsw_config` and `optimizers_config` set the index and optimizer parameters from the start (they can also be changed later with `qdrant_collection_update`); `on_disk_payload=true` keeps payloads on disk instead of in RAM, which can only be chosen here. Fails with a clear error if a collection with this name already exists. Example (simple): {"collection_name": "docs", "vector_size": 4, "distance": "Cosine"} Example (hybrid): {"collection_name": "docs", "vectors": { "dense": {"size": 4, "distance": "Cosine"} }, "sparse_vectors": {"sparse": {}}} Example (multitenant index, payload on disk): {"collection_name": "docs", "vector_size": 4, "hnsw_config": {"m": 0, "payload_m": 16}, "on_disk_payload": true} Example (text, semantic + BM25):…
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| distance | string | – | – |
| hnsw_config | – | – | – |
| metadata | – | – | – |
| on_disk_payload | – | – | – |
| optimizers_config | – | – | – |
| quantization_config | – | – | – |
| sparse_vectors | – | – | – |
| strict_mode_config | – | – | – |
| text_field | – | – | – |
| text_language | – | – | – |
| text_model | – | – | – |
| vector_size | – | – | – |
| vectors | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| config | – | yes | Current statistics and configuration of the collection |
| created_at | – | – | Time of the collection creation. Absent for collections created before Qdrant started recording it. |
| indexed_vectors_count | – | – | Approximate number of indexed vectors in the collection. Indexed vectors in large segments are faster to query, as it is stored in a specialized vector index. |
| optimizer_status | – | yes | Current statistics and configuration of the collection |
| payload_schema | object | yes | Types of stored payload |
| points_count | – | – | Approximate number of points (vectors + payloads) in collection. Each point could be accessed by unique id. |
| segments_count | integer | yes | Number of segments in collection. Each segment has independent vector as payload indexes |
| status | – | yes | Current statistics and configuration of the collection |
| update_queue | – | – | Update queue info |
| warnings | – | – | Warnings related to the collection |
No examples provided.
qdrant_collection_delete Delete Qdrant collection ~44
Delete a collection and all its points; a no-op if it doesn't exist. Example: {"collection_name": "docs"}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| deleted | boolean | yes | – |
No examples provided.
qdrant_collection_exists Check Qdrant collection existence ~40
Check whether a collection exists, without raising if it doesn't. Example: {"collection_name": "docs"}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| exists | boolean | yes | – |
No examples provided.
qdrant_collection_info Get Qdrant collection info ~48
Return full config and status of one collection. Fails with a clear error if the collection doesn't exist. Example: {"collection_name": "docs"}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| config | – | yes | Current statistics and configuration of the collection |
| created_at | – | – | Time of the collection creation. Absent for collections created before Qdrant started recording it. |
| indexed_vectors_count | – | – | Approximate number of indexed vectors in the collection. Indexed vectors in large segments are faster to query, as it is stored in a specialized vector index. |
| optimizer_status | – | yes | Current statistics and configuration of the collection |
| payload_schema | object | yes | Types of stored payload |
| points_count | – | – | Approximate number of points (vectors + payloads) in collection. Each point could be accessed by unique id. |
| segments_count | integer | yes | Number of segments in collection. Each segment has independent vector as payload indexes |
| status | – | yes | Current statistics and configuration of the collection |
| update_queue | – | – | Update queue info |
| warnings | – | – | Warnings related to the collection |
No examples provided.
qdrant_collection_list List Qdrant collections ~26
List every collection name in the configured Qdrant instance. Example: {}
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| collections | array | yes | – |
No examples provided.
qdrant_collection_update Update Qdrant collection ~368
Update optimizer/HNSW/collection/vector params on an existing collection. `text_models` declares which fastembed model made each existing dense vector (`{"<vector name>": "<model>"}`, `""` for the unnamed vector), so `query_text` and `text` upserts work on a collection built elsewhere — it must be the model the stored vectors were made with, and its size must match the vector's. `null` removes a declaration (e.g. after deleting that vector). A collection with points won't switch a vector to a different model: remove the declaration first if it was wrong. `text_field` names the payload field holding the text (default `text`). Both are kept in the collection's metadata. Only the fields you pass are changed; omitted ones keep their current value. `quantization_config="disabled"` turns quantization off. `vectors_config`/`sparse_vectors_config` only **adjust** named vectors that already exist (HNSW/quantization/index tuning) — they cannot add a new one; use `qdrant_collection_vector_create` for that, or this fails with Qdrant's own "Not existing vector name" error. Fails with a clear error if the collection doesn't exist. Example: {"collection_name": "docs", "optimizers_config": {"indexing_threshold": 10000}}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| collection_params | – | – | – |
| hnsw_config | – | – | – |
| optimizers_config | – | – | – |
| quantization_config | – | – | – |
| sparse_vectors_config | – | – | – |
| strict_mode_config | – | – | – |
| text_field | – | – | – |
| text_models | – | – | – |
| vectors_config | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| config | – | yes | Current statistics and configuration of the collection |
| created_at | – | – | Time of the collection creation. Absent for collections created before Qdrant started recording it. |
| indexed_vectors_count | – | – | Approximate number of indexed vectors in the collection. Indexed vectors in large segments are faster to query, as it is stored in a specialized vector index. |
| optimizer_status | – | yes | Current statistics and configuration of the collection |
| payload_schema | object | yes | Types of stored payload |
| points_count | – | – | Approximate number of points (vectors + payloads) in collection. Each point could be accessed by unique id. |
| segments_count | integer | yes | Number of segments in collection. Each segment has independent vector as payload indexes |
| status | – | yes | Current statistics and configuration of the collection |
| update_queue | – | – | Update queue info |
| warnings | – | – | Warnings related to the collection |
No examples provided.
qdrant_health_check Qdrant health check ~79
Confirm the configured Qdrant instance is reachable and responding. Never raises to the caller: a health check that raises on the exact condition it exists to detect defeats its own purpose. Connection failures are logged and reported in the result's ok/error fields instead, so a client renders them without a tool-call error round-trip.
Input schema present but exposes no named parameters.
| Name | Type | Req | Description |
|---|---|---|---|
| collection_count | – | – | – |
| error | – | – | – |
| ok | boolean | yes | – |
No examples provided.
qdrant_points_count Count Qdrant points ~52
Count points in a collection, optionally matching a filter. Example: {"collection_name": "docs"}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| count_filter | – | – | – |
| exact | boolean | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| count | integer | yes | Number of points which satisfy the conditions |
No examples provided.
qdrant_points_delete Delete Qdrant points ~147
Delete points by id list or by payload filter — exactly one of the two. Deleting an id that doesn't exist is not an error (Qdrant treats it as a no-op); this only fails if the collection itself is missing, or if you provide zero or both selectors. Example (by id): {"collection_name": "docs", "ids": [1, 2]} Example (by filter): {"collection_name": "docs", "points_filter": { "must": [{"key": "city", "match": {"value": "ny"}}] }}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| ids | – | – | – |
| points_filter | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| operation_id | – | – | Sequential number of the operation |
| status | – | yes | – |
No examples provided.
qdrant_points_get Get Qdrant points by id ~125
Retrieve points by id; unknown ids are simply omitted, not an error. Fails only if the collection itself doesn't exist. `with_payload` takes `true`/`false` or a list of keys to return only those (e.g. `["title"]`). Example: {"collection_name": "docs", "ids": [1, 2], "with_payload": ["title", "url"]}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| ids | array | yes | – |
| with_payload | – | – | – |
| with_vectors | boolean | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| points | array | yes | – |
No examples provided.
qdrant_points_scroll Scroll Qdrant points ~321
Page through all points in a collection, optionally filtered. Pass the returned `next_page_offset` as `offset` to fetch the next page; `null` means there are no more pages. `limit` is capped per call by the server's QDRANT_MCP_MAX_LIMIT (1000 by default). `with_payload` takes `true`/`false` or a list of keys to return only those. `order_by` sorts by a payload field instead of by id: a key, or `{"key": ..., "direction": "asc"|"desc", "start_from": value}`; the key needs a payload range index (integer, float or datetime). Paging works differently then: `offset` is rejected, and `next_page_offset` is always `null` even when more points remain — to continue, repeat the call with `start_from` set to the last value you received (points tied on that value are returned again, so de-duplicate by id). Example: {"collection_name": "docs", "limit": 50} Example (newest first): {"collection_name": "docs", "limit": 20, "order_by": {"key": "created_at", "direction": "desc"}}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| limit | integer | – | – |
| offset | – | – | – |
| order_by | – | – | – |
| scroll_filter | – | – | – |
| with_payload | – | – | – |
| with_vectors | boolean | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| next_page_offset | – | yes | – |
| points | array | yes | – |
No examples provided.
qdrant_points_upsert Upsert Qdrant points ~504
Insert or replace points (id + vector or text + payload) in a collection. `vector` matches the collection's vector config: a plain list for a single unnamed vector; a list of lists for an unnamed multivector; or a dict keyed by vector name for named vectors, where each value is a dense list, a multivector, or a sparse vector (`{"indices": [...], "values": [...]}`). Give `text` instead of `vector` to have it embedded with every model the collection declares (see `qdrant_collection_create`'s `text_model`) and stored in its text field — one text is one point, nothing is split. A text longer than the model reads (128 tokens, ~500 characters, for the multilingual MiniLM) is refused rather than silently cut: split it into several points. Needs the `embeddings` extra. `update_mode` makes the write conditional: `insert_only` never overwrites an existing id, `update_only` never creates a new one (default `upsert` does both). `update_filter` only overwrites existing points whose current payload matches the filter; ids that don't exist yet are inserted regardless (verified). `wait=false` returns before the write is applied. Fails with a clear error if the collection doesn't exist. Example: {"collection_name": "docs", "points": [ {"id": 1, "vector": [0.1, 0.2, 0.3, 0.4], "payload": {"city": "ny"}} ]} Example (text): {"collection_name": "notes", "points": [ {"id": 1, "text": "Grants for young people's housing", "payload": {"year": 2026}} ]} Example (named dense + sparse): {"collection_name": "docs", "points": [ {"id": 1, "vector": {"dense": [0.1, 0.2, 0.3, 0.4], "sparse": {"indices": [1, 7], "values": [0.5, 0.2]}}} ]}
| Name | Type | Req | Description |
|---|---|---|---|
| collection_name | string | yes | – |
| points | array | yes | – |
| update_filter | – | – | – |
| update_mode | – | – | – |
| wait | boolean | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| operation_id | – | – | Sequential number of the operation |
| status | – | yes | – |
No examples provided.
qdrant_query Query Qdrant ~1,716
Search a collection with Qdrant's unified Query API: vector similarity, hybrid fusion, multi-stage reranking, MMR diversity, payload-based score formulas, ordering by a payload field, or random sampling. Exactly one query mode is required: - `query_vector` — nearest points to a dense vector, a multivector (list of vectors), a sparse vector (`{"indices": [...], "values": [...]}`), or a point id whose stored vector is reused (that point itself is left out of the results). It must match the vector selected with `using`. Add `mmr` (`diversity` 0..1, `candidates_limit`) to re-order the nearest candidates for diversity: set `candidates_limit` well above `limit` (it defaults to `limit`, which leaves MMR nothing to choose from). `offset` pages through the MMR ranking on Qdrant 1.20 (verified; older servers applied it inside the `limit` re-ranked results, so raise `limit` there instead). - `query_text` — semantic search with plain text: embedded with the model the collection declares for the vector in `using` (`using` can be omitted when it declares exactly one). Needs the `embeddings` extra; `mmr` works as with `query_vector`. - `bm25_query` — keyword search ranked by BM25 (Qdrant 1.20): `using` is a payload field whose `text` index has `scoring` set (defaults to the collection's declared text field). The index's own tokenizer, stemmer and stopwords apply. Needs no embeddings. - `fusion` + 2+ `prefetch` stages — combine retrieval strategies: `"rrf"` (Reciprocal Rank Fusion), `"dbsf"` (Distribution-Based Score Fusion), or `{"method": "rrf", "weights": [2, 1], "k": 60}` for RRF with one weight per stage (a count that doesn't match the stages is rejected by Qdrant). - `formula` — rescore the results of `prefetch` stages (required: a formula without prefetch is rejected). `{"expression": ..., "defaults": {...}}`. An expression is a number; a variable (`"$score"` is the prefetch score, any other string is a payload key); a payload…
| Name | Type | Req | Description |
|---|---|---|---|
| bm25_query | – | – | – |
| collection_name | string | yes | – |
| consistency | – | – | – |
| formula | – | – | – |
| fusion | – | – | – |
| limit | integer | – | – |
| lookup_from | – | – | – |
| mmr | – | – | – |
| offset | – | – | – |
| order_by | – | – | – |
| prefetch | – | – | – |
| query_filter | – | – | – |
| query_text | – | – | – |
| query_vector | – | – | – |
| sample | – | – | – |
| score_threshold | – | – | – |
| search_params | – | – | – |
| timeout_seconds | – | – | – |
| using | – | – | – |
| with_payload | – | – | – |
| with_vectors | boolean | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| points | array | yes | – |
No examples provided.
How do I install the Qdrant MCP server?
Qdrant MCP runs locally as a PyPI package, launched with uvx mcp-qdrant. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · mcp-qdrant
claude mcp add avaazquezz-mcp-qdrant -- uvx mcp-qdrant
What is the Qdrant MCP server?
Qdrant MCP is listed in the public MCP registry as io.github.avaazquezz/mcp-qdrant. The full Qdrant API as 58 MCP tools: plain-text semantic/BM25/hybrid search and a search advisor. This page covers its PyPI package (mcp-qdrant).
Is the Qdrant MCP server safe to use?
Qdrant MCP scores 75 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Qdrant MCP server expose?
Qdrant MCP exposes 13 tools: qdrant_health_check, qdrant_collection_create, qdrant_collection_list, qdrant_collection_info, qdrant_collection_update, and 8 more. Their descriptions and schemas cost roughly 4,144 tokens of context every time the server is loaded.
Is the Qdrant MCP server still maintained?
Qdrant MCP is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Qdrant MCP server under?
Qdrant MCP declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.
What did VerifyMCP test on the Qdrant MCP server?
VerifyMCP ran 16 checks on Qdrant MCP, covering Malware scan, Known CVEs, Install scripts, Dependency health and 12 more. Endpoint Security and Transport & Reachability do not apply to a PyPI package, so they were not tested. The score does not measure everything, and the scoring documentation lists what it leaves out.