mcp-server-qdrant: a two-tool memory layer for MCP clients
An official Qdrant Model Context Protocol (MCP) server implementation
At a glance
- What is it?
- The official Qdrant MCP server exposes exactly two tools, qdrant-store and qdrant-find, and configures itself entirely through environment variables. It is a thin bridge between an LLM client and a Qdrant instance, and its limits follow directly from that design.
- Who is it for?
- Adopt mcp-server-qdrant if you already run Qdrant and want an MCP client to write and search memories without writing a client integration yourself. Do not adopt it if you need per-tenant collection routing enforced by the server, or if you expect the model to control filtering, since neither is in the documented surface.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap it fills between an MCP client and a vector database
An MCP client such as Claude, Cursor or Windsurf can call tools, but it has no built-in place to put facts it should remember later. Qdrant stores vectors and supports search, but it is a database, not a tool surface an LLM can call. This repository sits in the middle. The README describes it as "an official Model Context Protocol server for keeping and retrieving memories in the Qdrant vector search engine", acting as "a semantic memory layer on top of the Qdrant database". The intended user is someone who already has Qdrant running, either as a server or as a local path, and wants an off-the-shelf MCP endpoint rather than a custom integration. The README is also explicit that the repository doubles as "an example of how to create a MCP server for Qdrant", so it is both a usable artifact and a reference implementation. That dual purpose explains several choices, including the small tool count.
Two tools, and what their inputs actually allow
The entire tool surface is qdrant-store and qdrant-find. qdrant-store takes information as a string, an optional metadata JSON object, and a collection_name string. qdrant-find takes a query string and the same collection_name. Both tools return text: the store tool returns a confirmation message, and the find tool returns stored information as separate messages. That last detail matters for client behaviour. A search is not returned as one structured payload the model can parse; it arrives as a series of messages, one per result, which is why QDRANT_SEARCH_LIMIT defaults to 10 rather than something larger. The collection_name field has conditional behaviour worth reading twice: it is required when no default collection name is configured, and it is not enabled at all when a default exists. So the server is either collection-agnostic, with the model choosing a collection per call, or pinned to one collection, with the parameter hidden. There is no documented middle ground where the server validates the model's choice against an allowlist.
Configuration lives in environment variables, not a config file
There is no config file. The README states that configuration is done via environment variables and that the only command-line argument is --transport. The variables split into three groups. Connection: QDRANT_URL and QDRANT_API_KEY for a server, or QDRANT_LOCAL_PATH for a local database. The README carries an explicit note that you cannot provide both QDRANT_URL and QDRANT_LOCAL_PATH at the same time, so the two connection modes are mutually exclusive rather than merged. Embeddings: EMBEDDING_PROVIDER, which currently supports only fastembed, and EMBEDDING_MODEL, defaulting to sentence-transformers/all-MiniLM-L6-v2. Behaviour: COLLECTION_NAME, QDRANT_SEARCH_LIMIT (default 10), QDRANT_READ_ONLY (default false, which disables the qdrant-store tool), and TOOL_STORE_DESCRIPTION plus TOOL_FIND_DESCRIPTION for overriding how the tools are described to the model. Because the server is built on FastMCP, it also inherits that framework's variables, including FASTMCP_LOG_LEVEL, FASTMCP_SERVER_HOST, FASTMCP_SERVER_PORT, the three FASTMCP_SERVER_ON_DUPLICATE_* settings, and FASTMCP_SERVER_DEPENDENCIES. The README warns that server-specific settings use the FASTMCP_SERVER_ prefix and that this may change in future versions, which is a real upgrade hazard rather than a cosmetic note.
Running it with uvx and choosing a transport
The README's installation path avoids a separate install step by using uvx. The documented command passes configuration inline:
QDRANT_URL="http://localhost:6333" COLLECTION_NAME="my-collection" EMBEDDING_MODEL="sentence-transformers/all-MiniLM-L6-v2" uvx mcp-server-qdrant
The default transport is stdio, described as usable only by local MCP clients. For remote clients the README lists sse and streamable-http, selected with --transport, and notes that streamable-http is more recent than SSE. The port is not a flag; it comes from FASTMCP_SERVER_PORT, with 8000 as the default:
QDRANT_URL="http://localhost:6333" COLLECTION_NAME="my-collection" FASTMCP_SERVER_PORT=1234 uvx mcp-server-qdrant --transport sse
That split is worth internalising. Transport is a command-line decision; everything else is an environment decision. If you deploy this behind a network transport, the binding address comes from FASTMCP_SERVER_HOST, which defaults to 127.0.0.1, so a container or remote deployment needs that variable set deliberately.
Where the two-tool design becomes the wrong tool
The limitation is structural, not a bug. With no default collection configured, collection_name is a free string supplied by the model on every call. Nothing in the documented inputs constrains it to a known set, so a model that invents a collection name will create or target one. Multi-tenant deployments where each customer must be isolated to their own collection therefore cannot rely on the server to enforce that boundary; the isolation has to come from the Qdrant side, from separate server instances, or from a client that never exposes the raw parameter. The second gap is search control. qdrant-find accepts a query and a collection name. There is no documented input for metadata filters, score thresholds, or payload conditions, even though qdrant-store accepts arbitrary metadata. You can write structured metadata and you cannot query on it through this interface. For workloads where filtering is the point, this server is the wrong layer. The third constraint is the embedding model. EMBEDDING_PROVIDER currently supports only fastembed, so swapping in a hosted embedding API means modifying the server or waiting for provider support. Changing EMBEDDING_MODEL after data exists is worse than it sounds: vectors written under one model are not comparable with queries embedded under another, and the README does not describe a re-embedding path.
Compared with writing your own MCP server against the Qdrant client
The realistic alternative is not another product. It is a small MCP server you write yourself, using the Qdrant Python client directly, in the same way this repository is presented as an example of doing exactly that. The difference in approach is control over the tool contract. A custom server can expose a search tool that takes a filter object, can validate collection names against a fixed list, can return one structured result instead of a stream of messages, and can call a hosted embedding API rather than fastembed. What you give up is the maintenance the project already absorbs: FastMCP integration, the transport handling for stdio, sse and streamable-http, the read-only switch, and the tool-description overrides. If your requirements fit inside two tools with a query string and a collection name, writing your own is duplicated effort. If they do not, no amount of environment variable configuration will add the missing filter parameter, and the custom server is the shorter path.
Maintenance cost, versioning and the Apache-2.0 terms
The release cadence visible in the repository is uneven rather than steady: v0.7.1 in March 2025, v0.8.0 in June 2025, and v0.8.1 in December 2025. That pattern suggests a project that ships when something needs fixing rather than on a schedule, which is normal for an integration layer but means you should read release notes rather than assume a rhythm. Two upgrade risks are documented rather than hypothetical. First, the README states that server-specific FastMCP settings use the FASTMCP_SERVER_ prefix and that this may change in future versions, so any deployment that pins those variables is exposed to a rename. Second, the transport options are not equally settled: streamable-http is described as more recent than SSE, which implies SSE is the older path. The licence is Apache-2.0, which permits commercial use and modification and includes an explicit patent grant, with the usual obligations around retaining notices and stating changes. This is a description of the licence text, not legal advice; if you redistribute a modified server, have your own counsel confirm what notices you must carry.
Editorial conclusion
Adopt mcp-server-qdrant if you already run Qdrant and want an MCP client to write and search memories without writing a client integration yourself. Do not adopt it if you need per-tenant collection routing enforced by the server, or if you expect the model to control filtering, since neither is in the documented surface. Before wiring it into anything shared, verify three things in your own setup: that exactly one of QDRANT_URL or QDRANT_LOCAL_PATH is set, that QDRANT_READ_ONLY is true wherever the store tool should not exist, and that QDRANT_SEARCH_LIMIT matches what your client can absorb, since the default of 10 results arrives as separate messages.
Community notes