Merge pull request #13 from qdrant/chore/pre-commit

Add pre-commit to ensure consistent formatting
This commit is contained in:
Kacper Łukawski
2025-03-05 22:48:12 +01:00
committed by GitHub
8 changed files with 149 additions and 20 deletions

14
.github/workflows/pre-commit.yaml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: pre-commit
on:
pull_request:
push:
branches: [main]
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: pre-commit/action@v3.0.1

2
.gitignore vendored
View File

@@ -159,4 +159,4 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/

34
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,34 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
default_language_version:
python: python3.10
ci:
autofix_prs: true
autoupdate_commit_msg: '[pre-commit.ci] pre-commit suggestions'
autoupdate_schedule: quarterly
# submodules: true
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-ast
- id: check-added-large-files
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.0
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
name: "Sort Imports"
args: [ "--profile", "black" ]

View File

@@ -56,10 +56,10 @@ To use this server with the Claude Desktop app, add the following configuration
"qdrant": { "qdrant": {
"command": "uvx", "command": "uvx",
"args": [ "args": [
"mcp-server-qdrant", "mcp-server-qdrant",
"--qdrant-url", "--qdrant-url",
"http://localhost:6333", "http://localhost:6333",
"--qdrant-api-key", "--qdrant-api-key",
"your_api_key", "your_api_key",
"--collection-name", "--collection-name",
"your_collection_name" "your_collection_name"
@@ -68,8 +68,8 @@ To use this server with the Claude Desktop app, add the following configuration
} }
``` ```
Replace `http://localhost:6333`, `your_api_key` and `your_collection_name` with your Qdrant server URL, Qdrant API key Replace `http://localhost:6333`, `your_api_key` and `your_collection_name` with your Qdrant server URL, Qdrant API key
and collection name, respectively. The use of API key is optional, but recommended for security reasons, and depends on and collection name, respectively. The use of API key is optional, but recommended for security reasons, and depends on
the Qdrant server configuration. the Qdrant server configuration.
This MCP server will automatically create a collection with the specified name if it doesn't exist. This MCP server will automatically create a collection with the specified name if it doesn't exist.
@@ -87,7 +87,7 @@ To use a local mode of Qdrant, you can specify the path to the database using th
"qdrant": { "qdrant": {
"command": "uvx", "command": "uvx",
"args": [ "args": [
"mcp-server-qdrant", "mcp-server-qdrant",
"--qdrant-local-path", "--qdrant-local-path",
"/path/to/qdrant/database", "/path/to/qdrant/database",
"--collection-name", "--collection-name",
@@ -113,6 +113,6 @@ You cannot provide `QDRANT_URL` and `QDRANT_LOCAL_PATH` at the same time.
## License ## License
This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software,
subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project
repository. repository.

View File

@@ -14,7 +14,12 @@ requires = ["hatchling"]
build-backend = "hatchling.build" build-backend = "hatchling.build"
[tool.uv] [tool.uv]
dev-dependencies = ["pyright>=1.1.389", "pytest>=8.3.3", "ruff>=0.8.0"] dev-dependencies = [
"pre-commit>=4.1.0",
"pyright>=1.1.389",
"pytest>=8.3.3",
"ruff>=0.8.0",
]
[project.scripts] [project.scripts]
mcp-server-qdrant = "mcp_server_qdrant:main" mcp-server-qdrant = "mcp_server_qdrant:main"

View File

@@ -1,5 +1,6 @@
from typing import Optional from typing import Optional
from qdrant_client import AsyncQdrantClient, models
from qdrant_client import AsyncQdrantClient
class QdrantConnector: class QdrantConnector:
@@ -27,7 +28,9 @@ class QdrantConnector:
# For the time being, FastEmbed models are the only supported ones. # For the time being, FastEmbed models are the only supported ones.
# A list of all available models can be found here: # A list of all available models can be found here:
# https://qdrant.github.io/fastembed/examples/Supported_Models/ # https://qdrant.github.io/fastembed/examples/Supported_Models/
self._client = AsyncQdrantClient(location=qdrant_url, api_key=qdrant_api_key, path=qdrant_local_path) self._client = AsyncQdrantClient(
location=qdrant_url, api_key=qdrant_api_key, path=qdrant_local_path
)
self._client.set_model(fastembed_model_name) self._client.set_model(fastembed_model_name)
async def store_memory(self, information: str): async def store_memory(self, information: str):

View File

@@ -1,12 +1,11 @@
import asyncio
from typing import Optional from typing import Optional
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
import click import click
import mcp.types as types
import asyncio
import mcp import mcp
import mcp.types as types
from mcp.server import NotificationOptions, Server
from mcp.server.models import InitializationOptions
from .qdrant import QdrantConnector from .qdrant import QdrantConnector
@@ -29,7 +28,11 @@ def serve(
server = Server("qdrant") server = Server("qdrant")
qdrant = QdrantConnector( qdrant = QdrantConnector(
qdrant_url, qdrant_api_key, collection_name, fastembed_model_name, qdrant_local_path qdrant_url,
qdrant_api_key,
collection_name,
fastembed_model_name,
qdrant_local_path,
) )
@server.list_tools() @server.list_tools()
@@ -151,7 +154,9 @@ def main(
): ):
# XOR of url and local path, since we accept only one of them # XOR of url and local path, since we accept only one of them
if not (bool(qdrant_url) ^ bool(qdrant_local_path)): if not (bool(qdrant_url) ^ bool(qdrant_local_path)):
raise ValueError("Exactly one of qdrant-url or qdrant-local-path must be provided") raise ValueError(
"Exactly one of qdrant-url or qdrant-local-path must be provided"
)
async def _run(): async def _run():
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream): async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):

70
uv.lock generated
View File

@@ -38,6 +38,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 }, { url = "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", size = 167321 },
] ]
[[package]]
name = "cfgv"
version = "3.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 },
]
[[package]] [[package]]
name = "charset-normalizer" name = "charset-normalizer"
version = "3.4.0" version = "3.4.0"
@@ -140,6 +149,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018 }, { url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018 },
] ]
[[package]]
name = "distlib"
version = "0.3.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 },
]
[[package]] [[package]]
name = "exceptiongroup" name = "exceptiongroup"
version = "1.2.2" version = "1.2.2"
@@ -405,6 +423,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d7/de/85a784bcc4a3779d1753a7ec2dee5de90e18c7bcf402e71b51fcf150b129/hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15", size = 12389 }, { url = "https://files.pythonhosted.org/packages/d7/de/85a784bcc4a3779d1753a7ec2dee5de90e18c7bcf402e71b51fcf150b129/hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15", size = 12389 },
] ]
[[package]]
name = "identify"
version = "2.6.8"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f9/fa/5eb460539e6f5252a7c5a931b53426e49258cde17e3d50685031c300a8fd/identify-2.6.8.tar.gz", hash = "sha256:61491417ea2c0c5c670484fd8abbb34de34cdae1e5f39a73ee65e48e4bb663fc", size = 99249 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/78/8c/4bfcab2d8286473b8d83ea742716f4b79290172e75f91142bc1534b05b9a/identify-2.6.8-py2.py3-none-any.whl", hash = "sha256:83657f0f766a3c8d0eaea16d4ef42494b39b34629a4b3192a9d020d349b3e255", size = 99109 },
]
[[package]] [[package]]
name = "idna" name = "idna"
version = "3.10" version = "3.10"
@@ -455,7 +482,7 @@ wheels = [
[[package]] [[package]]
name = "mcp-server-qdrant" name = "mcp-server-qdrant"
version = "0.5.1" version = "0.5.2"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "mcp" }, { name = "mcp" },
@@ -464,6 +491,7 @@ dependencies = [
[package.dev-dependencies] [package.dev-dependencies]
dev = [ dev = [
{ name = "pre-commit" },
{ name = "pyright" }, { name = "pyright" },
{ name = "pytest" }, { name = "pytest" },
{ name = "ruff" }, { name = "ruff" },
@@ -477,6 +505,7 @@ requires-dist = [
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "pre-commit", specifier = ">=4.1.0" },
{ name = "pyright", specifier = ">=1.1.389" }, { name = "pyright", specifier = ">=1.1.389" },
{ name = "pytest", specifier = ">=8.3.3" }, { name = "pytest", specifier = ">=8.3.3" },
{ name = "ruff", specifier = ">=0.8.0" }, { name = "ruff", specifier = ">=0.8.0" },
@@ -719,6 +748,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/52/3b/ce7a01026a7cf46e5452afa86f97a5e88ca97f562cafa76570178ab56d8d/pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", size = 2554661 }, { url = "https://files.pythonhosted.org/packages/52/3b/ce7a01026a7cf46e5452afa86f97a5e88ca97f562cafa76570178ab56d8d/pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", size = 2554661 },
] ]
[[package]]
name = "platformdirs"
version = "4.3.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
]
[[package]] [[package]]
name = "pluggy" name = "pluggy"
version = "1.5.0" version = "1.5.0"
@@ -740,6 +778,22 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/9b/fb/a70a4214956182e0d7a9099ab17d50bfcba1056188e9b14f35b9e2b62a0d/portalocker-2.10.1-py3-none-any.whl", hash = "sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf", size = 18423 }, { url = "https://files.pythonhosted.org/packages/9b/fb/a70a4214956182e0d7a9099ab17d50bfcba1056188e9b14f35b9e2b62a0d/portalocker-2.10.1-py3-none-any.whl", hash = "sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf", size = 18423 },
] ]
[[package]]
name = "pre-commit"
version = "4.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cfgv" },
{ name = "identify" },
{ name = "nodeenv" },
{ name = "pyyaml" },
{ name = "virtualenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2a/13/b62d075317d8686071eb843f0bb1f195eb332f48869d3c31a4c6f1e063ac/pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4", size = 193330 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/43/b3/df14c580d82b9627d173ceea305ba898dca135feb360b6d84019d0803d3b/pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b", size = 220560 },
]
[[package]] [[package]]
name = "protobuf" name = "protobuf"
version = "5.28.3" version = "5.28.3"
@@ -1237,6 +1291,20 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/50/c1/2d27b0a15826c2b71dcf6e2f5402181ef85acf439617bb2f1453125ce1f3/uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e", size = 63828 }, { url = "https://files.pythonhosted.org/packages/50/c1/2d27b0a15826c2b71dcf6e2f5402181ef85acf439617bb2f1453125ce1f3/uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e", size = 63828 },
] ]
[[package]]
name = "virtualenv"
version = "20.29.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "distlib" },
{ name = "filelock" },
{ name = "platformdirs" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f1/88/dacc875dd54a8acadb4bcbfd4e3e86df8be75527116c91d8f9784f5e9cab/virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728", size = 4320272 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/93/fa/849483d56773ae29740ae70043ad88e068f98a6401aa819b5d6bee604683/virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a", size = 4301478 },
]
[[package]] [[package]]
name = "win32-setctime" name = "win32-setctime"
version = "1.1.0" version = "1.1.0"