Tools reference

This commit is contained in:
Chen, Li
2026-10-09 11:03:25 +08:00
parent e08f6c0525
commit 959fbcccb2
21 changed files with 1861 additions and 146 deletions
+89 -16
View File
@@ -1,31 +1,36 @@
from __future__ import annotations
from . import __version__
import json
import logging
from typing import Any, Protocol
from mcp.server import Server
from mcp.types import (
CallToolResult,
GetPromptResult,
ListPromptsResult,
ListResourcesResult,
ListToolsResult,
ReadResourceResult,
PaginatedRequestParams,
TextContent,
TextResourceContents,
Resource,
Tool,
Prompt
)
from .config import Config
from .prompts import PromptsManager
from . import __version__
from mini_db_mcp.config import Config
from mini_db_mcp.db import Database
from mini_db_mcp.domain.domain_catalog import DOMAIN_CATALOG
from mini_db_mcp.domain.domain_handler_factory import create_domain_registry
from mini_db_mcp.utils.pagination import paginate_list
from mini_db_mcp.prompts import PromptsManager
from mini_db_mcp.tools import ToolsManager
NAME = "mini-db-mcp"
logger = logging.getLogger(__name__)
class ResourcesProtocol(Protocol):
async def list_resources(self) -> list[Resource]: ...
@@ -35,7 +40,7 @@ class ResourcesProtocol(Protocol):
class ToolsProtocol(Protocol):
async def list_tools(self) -> list[Tool]: ...
async def call_tool(self, name: str, arguments: dict[str, Any]) -> str: ...
async def call_tool(self, name: str, arguments: dict[str, Any]) -> dict[str, Any]: ...
class PromptsProtocol(Protocol):
@@ -51,25 +56,61 @@ class MiniServer():
def __init__(self, config: Config) -> None:
self.config = config
self.prompts_manager = PromptsManager()
self.database = Database(config)
self.handler_registry = create_domain_registry(
metadata_store=self.database,
)
self.tools_manager = ToolsManager(
catalog=DOMAIN_CATALOG,
registry=self.handler_registry,
)
self.server = _create_mcp_server(
prompts_manager=self.prompts_manager
prompts_manager=self.prompts_manager,
tools_manager=self.tools_manager,
)
async def start_stdio(self) -> None:
from mcp.server.stdio import stdio_server
async with stdio_server() as streams:
read_stream, write_stream = streams
await self.server.run(
read_stream,
write_stream,
self.server.create_initialization_options(),
try:
async with stdio_server() as streams:
read_stream, write_stream = streams
await self.server.run(
read_stream,
write_stream,
self.server.create_initialization_options(),
)
finally:
await self.database.close()
async def start_http(self) -> None:
"""Serve MCP over stateless Streamable HTTP at ``/mcp``."""
import uvicorn
app = self.server.streamable_http_app(
streamable_http_path="/mcp",
json_response=True,
stateless_http=True,
host=self.config.server.host,
)
server = uvicorn.Server(
uvicorn.Config(
app,
host=self.config.server.host,
port=self.config.server.port,
log_level=self.config.server.log_level.lower(),
)
)
try:
await server.serve()
finally:
await self.database.close()
def _create_mcp_server(
*,
prompts_manager: PromptsProtocol | None = None,
tools_manager: ToolsProtocol | None = None,
) -> Server:
async def on_list_prompts(ctx, params):
@@ -78,11 +119,43 @@ def _create_mcp_server(
async def on_get_prompt(ctx, params):
return await prompts_manager.get_prompt(params.name, dict(params.arguments or {}))
async def list_tools(
ctx,
params: PaginatedRequestParams | None,
) -> ListToolsResult:
tools = await tools_manager.list_tools()
page_items, next_cursor = paginate_list(
tools,
cursor=params.cursor if params else None,
page_size=10,
identifier=lambda tool: tool.name,
)
logger.info("Returning %d of %d tools", len(page_items), len(tools))
return ListToolsResult(
tools=page_items,
next_cursor=next_cursor,
)
async def call_tool(ctx, params):
# ToolsManager returns either a manifest (discovery) or a child result.
result = await tools_manager.call_tool(
params.name,
dict(params.arguments or {}),
)
# Publish the same payload as structured data and backward-compatible text.
return CallToolResult(
content=[TextContent(type="text", text=json.dumps(result, ensure_ascii=False))],
structuredContent=result,
isError=result.get("mode") == "error",
)
server = Server(
name=NAME,
version=__version__,
on_list_prompts=on_list_prompts,
on_get_prompt=on_get_prompt,
on_list_tools=list_tools,
on_call_tool=call_tool,
)
return server