[tool.poetry]
name = "mcp-souschef"
version = "3.4.0"
description = "AI-powered MCP server for Chef to Ansible conversion"
readme = "README.md"
homepage = "https://github.com/kpeacocke/souschef"
repository = "https://github.com/kpeacocke/souschef"
documentation = "https://kpeacocke.github.io/souschef/"
keywords = ["chef", "ansible", "migration", "infrastructure", "automation", "mcp", "ai", "conversion"]
authors = ["SousChef Contributors"]
license = "MIT"
packages = [{include = "souschef"}]
classifiers = ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "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 :: Software Development :: Libraries :: Python Modules", "Topic :: System :: Systems Administration", "Topic :: Utilities"]
[tool.poetry.urls]
[tool.poetry.dependencies]
python = ">=3.10,<4.0"
click = ">=8.1.0"
mcp = ">=1.25.0"
python-dotenv = ">=1.2.1"
pyyaml = ">=6.0.0"
pydantic = ">=2.0.0"
requests = ">=2.31.0"
# Optional dependencies for different features
anthropic = {version = ">=0.75.0", optional = true}
openai = {version = ">=1.0.0", optional = true}
pandas = {version = ">=2.0.0", optional = true}
streamlit = {version = ">=1.28.0", optional = true}
plotly = {version = ">=5.17.0,<7.0", optional = true}
[tool.poetry.extras]
ai = ["anthropic", "openai"]
ui = ["pandas", "streamlit", "plotly"]
all = ["anthropic", "openai", "pandas", "streamlit", "plotly"]
[tool.poetry.group.dev.dependencies]
pytest = ">=9.0.2"
pytest-cov = ">=7.0.0"
pytest-benchmark = ">=5.1.0"
hypothesis = ">=6.125.0"
ruff = ">=0.14.10"
mypy = ">=1.14.0"
pip-audit = ">=2.7.0"
twine = ">=6.0.0"
pre-commit = ">=4.5.1"
mutmut = ">=3.4.0"
syrupy = "^5.0.0"
ansible-lint = ">=25.12.2,<27.0.0"
pytest-timeout = "^2.4.0"
types-pyyaml = "^6.0.12.20250915"
mkdocs = "^1.6.0"
mkdocs-material = "^9.5.0"
mkdocstrings = {extras = ["python"], version = ">=0.26,<1.1"}
mkdocs-git-revision-date-localized-plugin = "^1.2.0"
networkx = "^3.2.0"
matplotlib = "^3.8.0"
types-networkx = "^3.6.1.20251220"
types-requests = "^2.32.4.20260107"
types-urllib3 = "^1.26.25.14"
[tool.poetry.scripts]
souschef = "souschef.cli:main"
souschef-mcp = "souschef.server:main"
[build-system]
requires = ["poetry-core>=2.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.ruff]
line-length = 88
exclude = ["tools/"]
[tool.ruff.lint]
select = ["E", "F", "W", "C90", "I", "N", "UP", "B", "A", "C4", "T20", "SIM", "PTH", "ISC"]
# Docstring rules - use categories for maintainability; ignore specific exceptions
extend-select = ["D2", "D3", "D4"]
ignore = ["D100", "D104", "D105", "D107", "D203", "D212"]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
"tests/*" = ["S101", "E501"] # Allow assert statements, long lines in test data
"souschef/server.py" = ["T201", "E501", "ISC003"] # Allow print in main entry, long lines, explicit string concatenation
"souschef/assessment.py" = ["E501"] # Long lines in migration report templates
"souschef/parsers/validation.py" = ["E501"] # Long lines in validation messages
"souschef/converters/resource.py" = ["C901"] # Allow complex function for resource conversion logic
"souschef/deployment.py" = ["ISC003"] # Allow explicit string concatenation
"souschef/ui/app.py" = ["E402"] # Allow imports after path manipulation
"souschef/ui/pages/cookbook_analysis.py" = ["C901"] # Allow complex functions in UI code
[tool.pytest.ini_options]
minversion = "6.0"
addopts = "-ra -q --cov=souschef --cov-report=term-missing"
testpaths = [
"tests/unit",
"tests/integration",
"tests/e2e",
]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
[tool.coverage.run]
source = ["souschef"]
relative_files = true
omit = ["tests/*", "examples/*", "souschef/ui/*"]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
"if typing.TYPE_CHECKING:",
]
[tool.coverage.xml]
output = "coverage.xml"
[tool.coverage.paths]
source = [
"souschef/",
"*/souschef/",
]
[tool.mutmut]
backup = false
[tool.mypy]
python_version = "3.13"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
check_untyped_defs = true
warn_redundant_casts = true
warn_unused_ignores = true
strict_optional = true
no_implicit_optional = true
[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
check_untyped_defs = false
[[tool.mypy.overrides]]
module = [
"plotly.*",
"streamlit.*",
"mcp.*",
]
ignore_missing_imports = true