migrate to fastmcp 2 (#57)
* migrate to fastmcp 2 * format * ignore mypy being unreasonable * fmt * upd readme
This commit is contained in:
0
src/mcp_server_qdrant/common/__init__.py
Normal file
0
src/mcp_server_qdrant/common/__init__.py
Normal file
28
src/mcp_server_qdrant/common/func_tools.py
Normal file
28
src/mcp_server_qdrant/common/func_tools.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import inspect
|
||||
from functools import wraps
|
||||
from typing import Callable
|
||||
|
||||
|
||||
def make_partial_function(original_func: Callable, fixed_values: dict) -> Callable:
|
||||
sig = inspect.signature(original_func)
|
||||
|
||||
@wraps(original_func)
|
||||
def wrapper(*args, **kwargs):
|
||||
# Start with fixed values
|
||||
bound_args = dict(fixed_values)
|
||||
|
||||
# Bind positional/keyword args from caller
|
||||
for name, value in zip(remaining_params, args):
|
||||
bound_args[name] = value
|
||||
bound_args.update(kwargs)
|
||||
|
||||
return original_func(**bound_args)
|
||||
|
||||
# Only keep parameters NOT in fixed_values
|
||||
remaining_params = [name for name in sig.parameters if name not in fixed_values]
|
||||
new_params = [sig.parameters[name] for name in remaining_params]
|
||||
|
||||
# Set the new __signature__ for introspection
|
||||
wrapper.__signature__ = sig.replace(parameters=new_params) # type:ignore
|
||||
|
||||
return wrapper
|
||||
@@ -12,7 +12,7 @@ def main():
|
||||
parser = argparse.ArgumentParser(description="mcp-server-qdrant")
|
||||
parser.add_argument(
|
||||
"--transport",
|
||||
choices=["stdio", "sse"],
|
||||
choices=["stdio", "sse", "streamable-http"],
|
||||
default="stdio",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, List
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from mcp.server.fastmcp import Context, FastMCP
|
||||
from fastmcp import Context, FastMCP
|
||||
|
||||
from mcp_server_qdrant.common.func_tools import make_partial_function
|
||||
from mcp_server_qdrant.embeddings.factory import create_embedding_provider
|
||||
from mcp_server_qdrant.qdrant import Entry, Metadata, QdrantConnector
|
||||
from mcp_server_qdrant.settings import (
|
||||
@@ -67,7 +68,7 @@ class QdrantMCPServer(FastMCP):
|
||||
# The `metadata` parameter is defined as non-optional, but it can be None.
|
||||
# If we set it to be optional, some of the MCP clients, like Cursor, cannot
|
||||
# handle the optional parameter correctly.
|
||||
metadata: Metadata = None, # type: ignore
|
||||
metadata: Optional[Metadata] = None, # type: ignore
|
||||
) -> str:
|
||||
"""
|
||||
Store some information in Qdrant.
|
||||
@@ -87,16 +88,6 @@ class QdrantMCPServer(FastMCP):
|
||||
return f"Remembered: {information} in collection {collection_name}"
|
||||
return f"Remembered: {information}"
|
||||
|
||||
async def store_with_default_collection(
|
||||
ctx: Context,
|
||||
information: str,
|
||||
metadata: Metadata = None, # type: ignore
|
||||
) -> str:
|
||||
assert self.qdrant_settings.collection_name is not None
|
||||
return await store(
|
||||
ctx, information, self.qdrant_settings.collection_name, metadata
|
||||
)
|
||||
|
||||
async def find(
|
||||
ctx: Context,
|
||||
query: str,
|
||||
@@ -130,40 +121,27 @@ class QdrantMCPServer(FastMCP):
|
||||
content.append(self.format_entry(entry))
|
||||
return content
|
||||
|
||||
async def find_with_default_collection(
|
||||
ctx: Context,
|
||||
query: str,
|
||||
) -> List[str]:
|
||||
assert self.qdrant_settings.collection_name is not None
|
||||
return await find(ctx, query, self.qdrant_settings.collection_name)
|
||||
|
||||
# Register the tools depending on the configuration
|
||||
find_foo = find
|
||||
store_foo = store
|
||||
|
||||
if self.qdrant_settings.collection_name:
|
||||
self.add_tool(
|
||||
find_with_default_collection,
|
||||
name="qdrant-find",
|
||||
description=self.tool_settings.tool_find_description,
|
||||
find_foo = make_partial_function(
|
||||
find_foo, {"collection_name": self.qdrant_settings.collection_name}
|
||||
)
|
||||
else:
|
||||
self.add_tool(
|
||||
find,
|
||||
name="qdrant-find",
|
||||
description=self.tool_settings.tool_find_description,
|
||||
store_foo = make_partial_function(
|
||||
store_foo, {"collection_name": self.qdrant_settings.collection_name}
|
||||
)
|
||||
|
||||
self.add_tool(
|
||||
find_foo,
|
||||
name="qdrant-find",
|
||||
description=self.tool_settings.tool_find_description,
|
||||
)
|
||||
|
||||
if not self.qdrant_settings.read_only:
|
||||
# Those methods can modify the database
|
||||
|
||||
if self.qdrant_settings.collection_name:
|
||||
self.add_tool(
|
||||
store_with_default_collection,
|
||||
name="qdrant-store",
|
||||
description=self.tool_settings.tool_store_description,
|
||||
)
|
||||
else:
|
||||
self.add_tool(
|
||||
store,
|
||||
name="qdrant-store",
|
||||
description=self.tool_settings.tool_store_description,
|
||||
)
|
||||
self.add_tool(
|
||||
store_foo,
|
||||
name="qdrant-store",
|
||||
description=self.tool_settings.tool_store_description,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user