[project] name = "infrahub-mcp" version = "1.1.8" description = "MCP server to interact with Infrahub" readme = "README.md" requires-python = ">=3.13" dependencies = [ "fastmcp>=3.2.0", "infrahub-sdk>=1.22.0", "pydantic>=2.10,<3", "pydantic-settings>=2.6,<3", "python-dotenv>=1.0,<2", "toonify>=0.1.2", ] [project.scripts] infrahub-mcp = "infrahub_mcp:main" [dependency-groups] dev = [ "ty>=0.0.32", "rumdl>=0.1.68", "invoke>=2.2.0,<4.0.0", "mypy>=1.17.0", "pytest>=8.4.1", "pytest-asyncio>=1.1.0", "ruff>=0.15.11", "pylint>=4.0.5", "yamllint>=1.37.1", "infrahub-testcontainers>=1.10.0", "towncrier>=25.8.0", "pre-commit>=4.6.1", ] [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] filterwarnings = [] # Default run = unit only: exclude the integration marker and disable the # infrahub-sdk / testcontainers pytest plugins (pulled in by the # infrahub-testcontainers dev dependency) so the fast loop stays Docker-free. # Run the integration suite with: uv run pytest -m integration addopts = "-p no:pytest-infrahub -p no:pytest-infrahub-performance-test -m 'not integration'" markers = [ "integration: end-to-end tests against a real Infrahub container (require Docker; opt-in, excluded from the default run).", ] [tool.mypy] pretty = true ignore_missing_imports = true exclude = [ "server_initial\\.py$", # TOML's double-quoted strings require escaping backslashes "server_hackathon\\.py$", # TOML's double-quoted strings require escaping backslashes ] [tool.ruff] line-length = 120 exclude = [ ".git", ".venv", "env", "_build", "build", "dist", "examples", ] [tool.ruff.lint] preview = true task-tags = ["FIXME", "TODO"] select = ["ALL"] ignore = [ "D", # pydocstyle "DOC", # pydoclint "CPY", # flake8-copyright "T201", # use of `print` "ISC", # flake8-implicit-str-concat "COM812", # missing-trailing-comma "N999", # Invalid module name "TD", "FIX", # TODO "TRY", "B008", # Do not perform function call `Depends` in argument defaults "EM102", # Exception must not use an f-string literal "SIM117", # Use a single `with` statement with multiple contexts instead of nested `with` statements "G004", # Logging statement uses f-string "S311", # Standard pseudo-random generators are not suitable "LOG004", # `.exception()` call outside exception handlers "FBT", # Boolean-typed positional argument in function definition "ANN401", # Dynamically typed expressions (typing.Any) are disallowed in `value` "ERA001", # Found commented-out code # Two preview rules that ruff 0.16 turned on here (this config sets # `preview = true` with `select = ["ALL"]`). Both push ruff's new suppression # spelling: `noqa-comments` rewrites `# noqa: CODE` to `# ruff: ignore[CODE]` # (149 sites), and `rule-codes-in-selectors` wants rule names instead of codes # in this very list (25 sites) — ~175 lines rewritten for no behavioural gain. # Named, not coded, because `rule-codes-in-selectors` is the rule that objects # to codes here. "noqa-comments", "rule-codes-in-selectors", ] [tool.ruff.format] quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto" [tool.ruff.lint.isort] known-first-party = ["infrahub_mcp"] [tool.ruff.lint.pycodestyle] max-line-length = 150 [tool.ruff.lint.per-file-ignores] "tests/**/*.py" = [ "S101", # Allow assert in test files "ARG001", # Unused function args (protocol-matching callback stubs) "ARG002", # Unused method args (required by @patch decorators) "PLC2701", # Private name imports (testing internal helpers) "PLR2004", # Magic values in comparisons (expected in assertions) "PLR6301", # Method could be static (standard test-class pattern) "RUF076", # autouse fixtures are an intentional test-isolation pattern ] "src/infrahub_mcp/tools/write.py" = [ "PLW0717", # too-many-statements-in-try-clause — write flows wrap full SDK operations intentionally ] "scripts/**/*.py" = [ "BLE001", # Broad exception catch (acceptable in scripts) "EXE001", # Shebang without executable bit "PLC0415", # Import not at top level (lazy imports in scripts) "PLR0914", # Too many local variables "PLR0915", # Too many statements "PLR2004", # Magic values ] [tool.pylint.format] max-line-length = 120 [tool.pylint."messages control"] disable = [ "too-many-arguments", # R0913 — MCP tool functions have many params by design "too-many-positional-arguments", # R0917 — same reason "fixme", # W0511 — TODOs are tracked, not banned "missing-module-docstring", # C0114 — module docstrings add noise, ruff handles this "import-outside-toplevel", # C0415 — conditional/lazy imports are intentional "too-few-public-methods", # R0903 — ASGI middleware classes need only __call__ "invalid-name", # C0103 — module-level instances are intentionally lowercase "broad-exception-caught", # W0718 — health/lifespan endpoints catch-all intentionally "global-statement", # W0603 — middleware registry uses module-level state "no-else-return", # R1705 — stylistic, ruff handles this differently "protected-access", # W0212 — SDK workarounds require private member access "unused-argument", # W0613 — framework callback signatures require unused args ] [tool.uv] constraint-dependencies = [ "aiohttp>=3.13.3", "cryptography>=48.0.1", "dulwich>=1.2.5", "protobuf>=6.33.5", "pyasn1>=0.6.3", "pyjwt>=2.13.0", "python-multipart>=0.0.31", "requests>=2.33.0", "starlette>=1.3.1", "ujson>=5.13.0", "urllib3>=2.6.3", "wheel>=0.46.2", "pygments>=2.20.0", ] [tool.rumdl] # Disabled rules disable = ["MD013", "MD029", "MD033", "MD041"] # Opt-in rules extend-enable = ["MD060"] # File exclusions exclude = ["docs/docs/release-notes/**", "*-workspace/**"] # Per-file ignores [tool.rumdl.per-file-ignores] "**/AGENTS.md" = ["MD013", "MD024", "MD025", "MD029", "MD033", "MD041"] # MD024: allow duplicate headings among siblings only [tool.rumdl.MD024] siblings-only = true # MD025: don't treat frontmatter title as H1 [tool.rumdl.MD025] front-matter-title = "" # MD060: require leading and trailing pipes [tool.rumdl.MD060] enabled = true [tool.towncrier] package = "infrahub_mcp" directory = "changelog" filename = "CHANGELOG.md" start_string = "\n" underlines = ["", "", ""] title_format = "## [Infrahub MCP - v{version}](https://github.com/opsmill/infrahub-mcp/tree/v{version}) - {project_date}" issue_format = "[#{issue}](https://github.com/opsmill/infrahub-mcp/issues/{issue})" orphan_prefix = "+" template = "changelog/towncrier.md.template" [[tool.towncrier.type]] directory = "security" name = "Security" showcontent = true [[tool.towncrier.type]] directory = "removed" name = "Removed" showcontent = true [[tool.towncrier.type]] directory = "deprecated" name = "Deprecated" showcontent = true [[tool.towncrier.type]] directory = "added" name = "Added" showcontent = true [[tool.towncrier.type]] directory = "changed" name = "Changed" showcontent = true [[tool.towncrier.type]] directory = "fixed" name = "Fixed" showcontent = true [[tool.towncrier.type]] directory = "housekeeping" name = "Housekeeping" showcontent = true [tool.hatch.build.targets.wheel] packages = ["src/infrahub_mcp"] [build-system] requires = ["hatchling"] build-backend = "hatchling.build"