Handle parameters with environmental variables only (#24)
* Switch to Typer to read the CLI parameters and options * Rely on environmental variables only * Fix tests * Update README
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
from . import server
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point for the package."""
|
||||
server.mcp.run()
|
||||
|
||||
|
||||
# Optionally expose other important items at package level
|
||||
__all__ = ["main", "server"]
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
from .base import EmbeddingProvider
|
||||
from .factory import create_embedding_provider
|
||||
from .fastembed import FastEmbedProvider
|
||||
|
||||
__all__ = ["EmbeddingProvider", "FastEmbedProvider", "create_embedding_provider"]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from mcp_server_qdrant.embeddings import EmbeddingProvider
|
||||
from mcp_server_qdrant.embeddings.types import EmbeddingProviderType
|
||||
from mcp_server_qdrant.settings import EmbeddingProviderSettings
|
||||
|
||||
|
||||
@@ -8,7 +9,7 @@ def create_embedding_provider(settings: EmbeddingProviderSettings) -> EmbeddingP
|
||||
:param settings: The settings for the embedding provider.
|
||||
:return: An instance of the specified embedding provider.
|
||||
"""
|
||||
if settings.provider_type.lower() == "fastembed":
|
||||
if settings.provider_type == EmbeddingProviderType.FASTEMBED:
|
||||
from mcp_server_qdrant.embeddings.fastembed import FastEmbedProvider
|
||||
|
||||
return FastEmbedProvider(settings.model_name)
|
||||
|
||||
5
src/mcp_server_qdrant/embeddings/types.py
Normal file
5
src/mcp_server_qdrant/embeddings/types.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class EmbeddingProviderType(Enum):
|
||||
FASTEMBED = "fastembed"
|
||||
9
src/mcp_server_qdrant/main.py
Normal file
9
src/mcp_server_qdrant/main.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from mcp_server_qdrant.server import mcp
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main entry point for the mcp-server-qdrant script defined
|
||||
in pyproject.toml. It runs the MCP server.
|
||||
"""
|
||||
mcp.run()
|
||||
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
import os
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import AsyncIterator, List
|
||||
|
||||
@@ -8,27 +7,18 @@ from mcp.server.fastmcp import Context, FastMCP
|
||||
|
||||
from mcp_server_qdrant.embeddings.factory import create_embedding_provider
|
||||
from mcp_server_qdrant.qdrant import QdrantConnector
|
||||
from mcp_server_qdrant.settings import (
|
||||
EmbeddingProviderSettings,
|
||||
QdrantSettings,
|
||||
parse_args,
|
||||
)
|
||||
from mcp_server_qdrant.settings import EmbeddingProviderSettings, QdrantSettings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Parse command line arguments and set them as environment variables.
|
||||
# This is done for backwards compatibility with the previous versions
|
||||
# of the MCP server.
|
||||
env_vars = parse_args()
|
||||
for key, value in env_vars.items():
|
||||
os.environ[key] = value
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def server_lifespan(server: Server) -> AsyncIterator[dict]: # noqa
|
||||
"""
|
||||
Context manager to handle the lifespan of the server.
|
||||
This is used to configure the embedding provider and Qdrant connector.
|
||||
All the configuration is now loaded from the environment variables.
|
||||
Settings handle that for us.
|
||||
"""
|
||||
try:
|
||||
# Embedding provider is created with a factory function so we can add
|
||||
@@ -63,7 +53,7 @@ async def server_lifespan(server: Server) -> AsyncIterator[dict]: # noqa
|
||||
pass
|
||||
|
||||
|
||||
mcp = FastMCP("Qdrant", lifespan=server_lifespan)
|
||||
mcp = FastMCP("mcp-server-qdrant", lifespan=server_lifespan)
|
||||
|
||||
|
||||
@mcp.tool(
|
||||
@@ -116,7 +106,3 @@ async def find(query: str, ctx: Context) -> List[str]:
|
||||
for entry in entries:
|
||||
content.append(f"<entry>{entry}</entry>")
|
||||
return content
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run()
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import argparse
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import Field
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
from mcp_server_qdrant.embeddings.types import EmbeddingProviderType
|
||||
|
||||
|
||||
class EmbeddingProviderSettings(BaseSettings):
|
||||
"""
|
||||
Configuration for the embedding provider.
|
||||
"""
|
||||
|
||||
provider_type: str = Field(
|
||||
default="fastembed", validation_alias="EMBEDDING_PROVIDER"
|
||||
provider_type: EmbeddingProviderType = Field(
|
||||
default=EmbeddingProviderType.FASTEMBED,
|
||||
validation_alias="EMBEDDING_PROVIDER",
|
||||
)
|
||||
model_name: str = Field(
|
||||
default="sentence-transformers/all-MiniLM-L6-v2",
|
||||
@@ -36,66 +38,3 @@ class QdrantSettings(BaseSettings):
|
||||
Get the Qdrant location, either the URL or the local path.
|
||||
"""
|
||||
return self.location or self.local_path
|
||||
|
||||
|
||||
def parse_args() -> Dict[str, Any]:
|
||||
"""
|
||||
Parse command line arguments for the MCP server.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Dictionary of parsed arguments
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description="Qdrant MCP Server")
|
||||
|
||||
# Qdrant connection options
|
||||
connection_group = parser.add_mutually_exclusive_group()
|
||||
connection_group.add_argument(
|
||||
"--qdrant-url",
|
||||
help="URL of the Qdrant server, e.g. http://localhost:6333",
|
||||
)
|
||||
connection_group.add_argument(
|
||||
"--qdrant-local-path",
|
||||
help="Path to the local Qdrant database",
|
||||
)
|
||||
|
||||
# Other Qdrant settings
|
||||
parser.add_argument(
|
||||
"--qdrant-api-key",
|
||||
help="API key for the Qdrant server",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--collection-name",
|
||||
help="Name of the collection to use",
|
||||
)
|
||||
|
||||
# Embedding settings
|
||||
parser.add_argument(
|
||||
"--embedding-provider",
|
||||
help="Embedding provider to use (currently only 'fastembed' is supported)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--embedding-model",
|
||||
help="Name of the embedding model to use",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Convert to dictionary and filter out None values
|
||||
args_dict = {k: v for k, v in vars(args).items() if v is not None}
|
||||
|
||||
# Convert argument names to environment variable format
|
||||
env_vars = {}
|
||||
if "qdrant_url" in args_dict:
|
||||
env_vars["QDRANT_URL"] = args_dict["qdrant_url"]
|
||||
if "qdrant_api_key" in args_dict:
|
||||
env_vars["QDRANT_API_KEY"] = args_dict["qdrant_api_key"]
|
||||
if "collection_name" in args_dict:
|
||||
env_vars["COLLECTION_NAME"] = args_dict["collection_name"]
|
||||
if "embedding_model" in args_dict:
|
||||
env_vars["EMBEDDING_MODEL"] = args_dict["embedding_model"]
|
||||
if "embedding_provider" in args_dict:
|
||||
env_vars["EMBEDDING_PROVIDER"] = args_dict["embedding_provider"]
|
||||
if "qdrant_local_path" in args_dict:
|
||||
env_vars["QDRANT_LOCAL_PATH"] = args_dict["qdrant_local_path"]
|
||||
|
||||
return env_vars
|
||||
|
||||
Reference in New Issue
Block a user