Skip to content

Commit e6961ce

Browse files
authored
Merge pull request #19 from laurigates/pr-1-fastmcp-2.0-migration
FastMCP 2.0 Migration & Foundation
2 parents b4d3bfa + af947ee commit e6961ce

File tree

3 files changed

+69
-15
lines changed

3 files changed

+69
-15
lines changed

kicad_mcp/server.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
import os
66
import signal
77
import logging
8+
import functools
89
from typing import Callable
9-
from mcp.server.fastmcp import FastMCP
10+
from fastmcp import FastMCP
1011

1112
# Import resource handlers
1213
from kicad_mcp.resources.projects import register_project_resources
@@ -127,9 +128,11 @@ def create_server() -> FastMCP:
127128
# Always print this now, as we rely on CLI
128129
logging.info(f"KiCad Python module setup removed; relying on kicad-cli for external operations.")
129130

131+
# Build a lifespan callable with the kwarg baked in (FastMCP 2.x dropped lifespan_kwargs)
132+
lifespan_factory = functools.partial(kicad_lifespan, kicad_modules_available=kicad_modules_available)
133+
130134
# Initialize FastMCP server
131-
# Pass the availability flag (always False now) to the lifespan context
132-
mcp = FastMCP("KiCad", lifespan=kicad_lifespan, lifespan_kwargs={"kicad_modules_available": kicad_modules_available})
135+
mcp = FastMCP("KiCad", lifespan=lifespan_factory)
133136
logging.info(f"Created FastMCP server instance with lifespan management")
134137

135138
# Register resources
@@ -186,3 +189,43 @@ def cleanup_temp_dirs():
186189

187190
logging.info(f"Server initialization complete")
188191
return mcp
192+
193+
194+
def setup_signal_handlers() -> None:
195+
"""Setup signal handlers for graceful shutdown."""
196+
# Signal handlers are set up in register_signal_handlers
197+
pass
198+
199+
200+
def cleanup_handler() -> None:
201+
"""Handle cleanup during shutdown."""
202+
run_cleanup_handlers()
203+
204+
205+
def setup_logging() -> None:
206+
"""Configure logging for the server."""
207+
logging.basicConfig(
208+
level=logging.INFO,
209+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
210+
)
211+
212+
213+
def main() -> None:
214+
"""Start the KiCad MCP server (blocking)."""
215+
setup_logging()
216+
logging.info("Starting KiCad MCP server...")
217+
218+
server = create_server()
219+
220+
try:
221+
server.run() # FastMCP manages its own event loop
222+
except KeyboardInterrupt:
223+
logging.info("Server interrupted by user")
224+
except Exception as e:
225+
logging.error(f"Server error: {e}")
226+
finally:
227+
logging.info("Server shutdown complete")
228+
229+
230+
if __name__ == "__main__":
231+
main()

main.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
# Must import config BEFORE env potentially overrides it via os.environ
1111
from kicad_mcp.config import KICAD_USER_DIR, ADDITIONAL_SEARCH_PATHS
12-
from kicad_mcp.server import create_server
12+
from kicad_mcp.server import main as server_main
1313
from kicad_mcp.utils.env import load_dotenv
1414

1515
# --- Setup Logging ---
@@ -70,10 +70,10 @@
7070
else:
7171
logging.info(f"No additional search paths configured") # Changed print to logging
7272

73-
# Create and run server
74-
server = create_server()
73+
# Run server
7574
logging.info(f"Running server with stdio transport") # Changed print to logging
76-
server.run(transport='stdio')
75+
import asyncio
76+
asyncio.run(server_main())
7777
except Exception as e:
7878
logging.exception(f"Unhandled exception in main") # Log exception details
7979
raise

pyproject.toml

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,47 @@
11
[build-system]
2-
requires = ["setuptools>=61.0", "wheel"]
3-
build-backend = "setuptools.build_meta"
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
44

55
[project]
66
name = "kicad-mcp"
77
version = "0.1.0"
8-
authors = [{ name = "Lama Al Rajih" }]
9-
description = "Model Context Protocol server for KiCad on Mac, Windows, and Linux"
10-
license = { text = "MIT" }
8+
description = "Model Context Protocol (MCP) server for KiCad electronic design automation (EDA) files"
119
readme = "README.md"
10+
license = { text = "MIT" }
11+
authors = [
12+
{ name = "KiCad MCP Contributors" }
13+
]
1214
requires-python = ">=3.10"
15+
dependencies = [
16+
"mcp[cli]>=1.0.0",
17+
"fastmcp>=0.1.0",
18+
"pandas>=2.0.0",
19+
]
1320
classifiers = [
1421
"Programming Language :: Python :: 3",
1522
"Programming Language :: Python :: 3.10",
1623
"Programming Language :: Python :: 3.11",
1724
"Programming Language :: Python :: 3.12",
1825
"License :: OSI Approved :: MIT License",
1926
"Operating System :: OS Independent",
20-
"Development Status :: 4 - Beta",
2127
"Intended Audience :: Developers",
2228
"Topic :: Software Development :: Libraries :: Python Modules",
2329
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
2430
]
25-
dependencies = ["mcp[cli]>=1.11.0", "pandas>=2.3.1", "pytest>=8.4.1"]
2631

2732
[project.urls]
2833
"Homepage" = "https://github.com/lamaalrajih/kicad-mcp"
2934
"Bug Tracker" = "https://github.com/lamaalrajih/kicad-mcp/issues"
3035
"Documentation" = "https://github.com/lamaalrajih/kicad-mcp#readme"
3136

3237
[project.scripts]
33-
kicad-mcp = "kicad_mcp.main:main"
38+
kicad-mcp = "kicad_mcp.server:main"
39+
40+
[dependency-groups]
41+
dev = [
42+
"pytest>=7.0.0",
43+
"pytest-asyncio>=0.23.0",
44+
]
3445

3546
[tool.setuptools.packages.find]
3647
where = ["."]

0 commit comments

Comments
 (0)