Merge pull request #19 from laurigates/pr-1-fastmcp-2.0-migration

FastMCP 2.0 Migration & Foundation
This commit is contained in:
Lama Al Rajih 2025-07-21 13:26:18 -04:00 committed by GitHub
commit e6961ceefb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 15 deletions

View File

@ -5,8 +5,9 @@ import atexit
import os import os
import signal import signal
import logging import logging
import functools
from typing import Callable from typing import Callable
from mcp.server.fastmcp import FastMCP from fastmcp import FastMCP
# Import resource handlers # Import resource handlers
from kicad_mcp.resources.projects import register_project_resources from kicad_mcp.resources.projects import register_project_resources
@ -127,9 +128,11 @@ def create_server() -> FastMCP:
# Always print this now, as we rely on CLI # Always print this now, as we rely on CLI
logging.info(f"KiCad Python module setup removed; relying on kicad-cli for external operations.") logging.info(f"KiCad Python module setup removed; relying on kicad-cli for external operations.")
# Build a lifespan callable with the kwarg baked in (FastMCP 2.x dropped lifespan_kwargs)
lifespan_factory = functools.partial(kicad_lifespan, kicad_modules_available=kicad_modules_available)
# Initialize FastMCP server # Initialize FastMCP server
# Pass the availability flag (always False now) to the lifespan context mcp = FastMCP("KiCad", lifespan=lifespan_factory)
mcp = FastMCP("KiCad", lifespan=kicad_lifespan, lifespan_kwargs={"kicad_modules_available": kicad_modules_available})
logging.info(f"Created FastMCP server instance with lifespan management") logging.info(f"Created FastMCP server instance with lifespan management")
# Register resources # Register resources
@ -186,3 +189,43 @@ def create_server() -> FastMCP:
logging.info(f"Server initialization complete") logging.info(f"Server initialization complete")
return mcp return mcp
def setup_signal_handlers() -> None:
"""Setup signal handlers for graceful shutdown."""
# Signal handlers are set up in register_signal_handlers
pass
def cleanup_handler() -> None:
"""Handle cleanup during shutdown."""
run_cleanup_handlers()
def setup_logging() -> None:
"""Configure logging for the server."""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
def main() -> None:
"""Start the KiCad MCP server (blocking)."""
setup_logging()
logging.info("Starting KiCad MCP server...")
server = create_server()
try:
server.run() # FastMCP manages its own event loop
except KeyboardInterrupt:
logging.info("Server interrupted by user")
except Exception as e:
logging.error(f"Server error: {e}")
finally:
logging.info("Server shutdown complete")
if __name__ == "__main__":
main()

View File

@ -9,7 +9,7 @@ import logging # Import logging module
# Must import config BEFORE env potentially overrides it via os.environ # Must import config BEFORE env potentially overrides it via os.environ
from kicad_mcp.config import KICAD_USER_DIR, ADDITIONAL_SEARCH_PATHS from kicad_mcp.config import KICAD_USER_DIR, ADDITIONAL_SEARCH_PATHS
from kicad_mcp.server import create_server from kicad_mcp.server import main as server_main
from kicad_mcp.utils.env import load_dotenv from kicad_mcp.utils.env import load_dotenv
# --- Setup Logging --- # --- Setup Logging ---
@ -70,10 +70,10 @@ if __name__ == "__main__":
else: else:
logging.info(f"No additional search paths configured") # Changed print to logging logging.info(f"No additional search paths configured") # Changed print to logging
# Create and run server # Run server
server = create_server()
logging.info(f"Running server with stdio transport") # Changed print to logging logging.info(f"Running server with stdio transport") # Changed print to logging
server.run(transport='stdio') import asyncio
asyncio.run(server_main())
except Exception as e: except Exception as e:
logging.exception(f"Unhandled exception in main") # Log exception details logging.exception(f"Unhandled exception in main") # Log exception details
raise raise

View File

@ -1,15 +1,22 @@
[build-system] [build-system]
requires = ["setuptools>=61.0", "wheel"] requires = ["hatchling"]
build-backend = "setuptools.build_meta" build-backend = "hatchling.build"
[project] [project]
name = "kicad-mcp" name = "kicad-mcp"
version = "0.1.0" version = "0.1.0"
authors = [{ name = "Lama Al Rajih" }] description = "Model Context Protocol (MCP) server for KiCad electronic design automation (EDA) files"
description = "Model Context Protocol server for KiCad on Mac, Windows, and Linux"
license = { text = "MIT" }
readme = "README.md" readme = "README.md"
license = { text = "MIT" }
authors = [
{ name = "KiCad MCP Contributors" }
]
requires-python = ">=3.10" requires-python = ">=3.10"
dependencies = [
"mcp[cli]>=1.0.0",
"fastmcp>=0.1.0",
"pandas>=2.0.0",
]
classifiers = [ classifiers = [
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
@ -17,12 +24,10 @@ classifiers = [
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"License :: OSI Approved :: MIT License", "License :: OSI Approved :: MIT License",
"Operating System :: OS Independent", "Operating System :: OS Independent",
"Development Status :: 4 - Beta",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
] ]
dependencies = ["mcp[cli]>=1.11.0", "pandas>=2.3.1", "pytest>=8.4.1"]
[project.urls] [project.urls]
"Homepage" = "https://github.com/lamaalrajih/kicad-mcp" "Homepage" = "https://github.com/lamaalrajih/kicad-mcp"
@ -30,7 +35,13 @@ dependencies = ["mcp[cli]>=1.11.0", "pandas>=2.3.1", "pytest>=8.4.1"]
"Documentation" = "https://github.com/lamaalrajih/kicad-mcp#readme" "Documentation" = "https://github.com/lamaalrajih/kicad-mcp#readme"
[project.scripts] [project.scripts]
kicad-mcp = "kicad_mcp.main:main" kicad-mcp = "kicad_mcp.server:main"
[dependency-groups]
dev = [
"pytest>=7.0.0",
"pytest-asyncio>=0.23.0",
]
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
where = ["."] where = ["."]