[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "kicad-mcp" version = "0.1.0" description = "Model Context Protocol (MCP) server for KiCad electronic design automation (EDA) files" readme = "README.md" license = { text = "MIT" } authors = [ { name = "KiCad MCP Contributors" } ] maintainers = [ { name = "KiCad MCP Contributors" } ] keywords = [ "kicad", "eda", "electronics", "schematic", "pcb", "mcp", "model-context-protocol", "ai", "assistant" ] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: Manufacturing", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", "Topic :: Software Development :: Libraries :: Python Modules", "Typing :: Typed" ] requires-python = ">=3.10" dependencies = [ "mcp[cli]>=1.0.0", "fastmcp>=2.0.0", "pandas>=2.0.0", "pyyaml>=6.0.0", "defusedxml>=0.7.0", # Secure XML parsing ] classifiers = [ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", ] [project.urls] "Homepage" = "https://github.com/lamaalrajih/kicad-mcp" "Bug Tracker" = "https://github.com/lamaalrajih/kicad-mcp/issues" "Documentation" = "https://github.com/lamaalrajih/kicad-mcp#readme" [project.scripts] kicad-mcp = "kicad_mcp.server:main" [dependency-groups] dev = [ "pytest>=7.0.0", "pytest-asyncio>=0.23.0", "pytest-mock>=3.10.0", "pytest-cov>=4.0.0", "pytest-xdist>=3.0.0", "ruff>=0.1.0", "mypy>=1.8.0", "pre-commit>=3.0.0", "bandit>=1.7.0", # Security linting for pre-commit hooks ] docs = [ "sphinx>=7.0.0", "sphinx-rtd-theme>=1.3.0", "myst-parser>=2.0.0", ] security = [ "bandit>=1.7.0", "safety>=3.0.0", ] performance = [ "memory-profiler>=0.61.0", "py-spy>=0.3.0", ] visualization = [ "cairosvg>=2.7.0", # SVG to PNG conversion "Pillow>=10.0.0", # Image processing "playwright>=1.40.0", # Browser automation (optional) ] [tool.ruff] target-version = "py310" line-length = 100 [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "SIM", # flake8-simplify "UP", # pyupgrade ] ignore = [ "E501", # line too long, handled by ruff format "B008", # do not perform function calls in argument defaults "C901", # too complex (handled by other tools) "B905", # zip() without an explicit strict= parameter ] unfixable = [ "B", # Avoid trying to fix flake8-bugbear violations ] [tool.ruff.lint.per-file-ignores] "tests/**/*.py" = [ "S101", # Use of assert detected "D103", # Missing docstring in public function "SLF001", # Private member accessed ] "kicad_mcp/config.py" = [ "E501", # Long lines in config are ok ] [tool.ruff.lint.isort] known-first-party = ["kicad_mcp"] force-sort-within-sections = true [tool.ruff.format] quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto" [tool.mypy] python_version = "3.11" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = false disallow_incomplete_defs = false check_untyped_defs = true disallow_untyped_decorators = false no_implicit_optional = true warn_redundant_casts = true warn_unused_ignores = true warn_no_return = true warn_unreachable = true strict_equality = true show_error_codes = true [[tool.mypy.overrides]] module = [ "pandas.*", "mcp.*", ] ignore_missing_imports = true [tool.pytest.ini_options] minversion = "7.0" addopts = [ "--strict-markers", "--strict-config", "--cov=kicad_mcp", "--cov-report=term-missing", "--cov-report=html:htmlcov", "--cov-report=xml", "--cov-fail-under=80", "-ra", "--tb=short", ] testpaths = ["tests"] python_files = ["test_*.py"] python_classes = ["Test*"] python_functions = ["test_*"] markers = [ "unit: Unit tests", "integration: Integration tests", "slow: Tests that take more than a few seconds", "requires_kicad: Tests that require KiCad CLI to be installed", "performance: Performance benchmarking tests", ] asyncio_mode = "auto" filterwarnings = [ "ignore::DeprecationWarning", "ignore::PendingDeprecationWarning", "ignore::RuntimeWarning:asyncio", ] [tool.coverage.run] source = ["kicad_mcp"] branch = true omit = [ "tests/*", "kicad_mcp/__init__.py", "*/migrations/*", "*/venv/*", "*/.venv/*", ] [tool.coverage.report] precision = 2 show_missing = true skip_covered = false exclude_lines = [ "pragma: no cover", "def __repr__", "if self.debug:", "if settings.DEBUG", "raise AssertionError", "raise NotImplementedError", "if 0:", "if __name__ == .__main__.:", "class .*\\bProtocol\\):", "@(abc\\.)?abstractmethod", ] [tool.bandit] exclude_dirs = ["tests", "build", "dist"] skips = ["B101", "B601", "B404", "B603", "B110", "B112"] # Skip low-severity subprocess and exception handling warnings [tool.bandit.assert_used] skips = ["*_test.py", "*/test_*.py"] [tool.setuptools.packages.find] where = ["."] include = ["kicad_mcp*"] exclude = ["tests*", "docs*"] [tool.setuptools.package-data] "kicad_mcp" = ["prompts/*.txt", "resources/**/*.json"]