""" mckicad MCP server — FastMCP 3 architecture. Tools are registered via module-level @mcp.tool decorators in their respective modules. Importing the module is all that's needed. """ from contextlib import asynccontextmanager import logging from typing import Any from fastmcp import FastMCP from mckicad.config import get_kicad_user_dir, get_search_paths logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(server: FastMCP): """Manage server lifecycle — initialize shared state, yield, clean up.""" logger.info("mckicad server starting") kicad_user_dir = get_kicad_user_dir() search_paths = get_search_paths() logger.info(f"KiCad user dir: {kicad_user_dir}") logger.info(f"Search paths: {search_paths}") state: dict[str, Any] = { "cache": {}, "kicad_user_dir": kicad_user_dir, "search_paths": search_paths, } try: yield state finally: state["cache"].clear() logger.info("mckicad server stopped") mcp = FastMCP("mckicad", lifespan=lifespan) # Import tool/resource/prompt modules so their decorators register with `mcp`. # Order doesn't matter — each module does @mcp.tool() at module level. from mckicad.prompts import templates # noqa: E402, F401 from mckicad.resources import files, projects # noqa: E402, F401 from mckicad.resources import schematic as schematic_resources # noqa: E402, F401 from mckicad.tools import ( # noqa: E402, F401 analysis, batch, bom, drc, export, netlist, pcb, power_symbols, project, routing, schematic, schematic_analysis, schematic_edit, schematic_patterns, ) def main(): mcp.run(transport="stdio")