Skip to main content
Glama
common.py3.53 kB
"""Common utilities for MCP tool registration. Provides factories and helpers for registering tools with consistent patterns. """ from dataclasses import dataclass from datetime import UTC, datetime from types import SimpleNamespace from typing import Any from cribl_control_plane.models.security import Security from fastmcp import Context from ..operations.common import CollectorFunc, ProductResult @dataclass(frozen=True, slots=True) class ToolConfig: """Configuration for a generic list tool.""" collector: CollectorFunc section_name: str log_message: str requires_security: bool = False async def collect_for_products( deps: SimpleNamespace, collector: CollectorFunc, *, requires_security: bool = False, ) -> dict[str, ProductResult]: """Collect data across all products using the given collector function. Args: deps: Dependencies namespace with config, products, token_manager, create_cp. collector: Async function to call for each product. requires_security: Whether the collector requires a security parameter. Returns: Dictionary mapping product names to their collected results. """ results: dict[str, ProductResult] = {} security: Security = await deps.token_manager.get_security() async with deps.create_cp(deps.config, security=security) as client: for product in deps.products: if requires_security: result = await collector( client, security=security, product=product, timeout_ms=deps.config.timeout_ms, ctx=deps.ctx, ) else: result = await collector( client, product=product, timeout_ms=deps.config.timeout_ms, ctx=deps.ctx, ) results[product.value] = result return results def build_tool_response( deps: SimpleNamespace, section_name: str, data: dict[str, ProductResult], ) -> dict[str, Any]: """Build a standard tool response with metadata. Args: deps: Dependencies namespace with config. section_name: Name of the data section (e.g., "sources", "destinations"). data: Collected data to include in the response. Returns: Standard response dictionary with metadata. """ return { "retrieved_at": datetime.now(UTC).isoformat(), "base_url": deps.config.base_url_str, section_name: data, } async def generic_list_tool( ctx: Context, deps: SimpleNamespace, tool_config: ToolConfig, ) -> dict[str, Any]: """Generic implementation for list tools. Args: ctx: FastMCP context. deps: Dependencies namespace. tool_config: Configuration for the tool including collector and settings. Returns: Tool response dictionary. """ await ctx.info(tool_config.log_message) # Inject context into deps for the collector deps_with_ctx = SimpleNamespace(**vars(deps), ctx=ctx) results = await collect_for_products( deps_with_ctx, tool_config.collector, requires_security=tool_config.requires_security, ) return build_tool_response(deps, tool_config.section_name, results) __all__ = [ "CollectorFunc", "ProductResult", "ToolConfig", "build_tool_response", "collect_for_products", "generic_list_tool", ]

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/atree1023/snc-cribl-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server