[project] name = "cost-guard-mcp" version = "0.3.0" description = "Pre-flight query cost & result-size guardrails for AI agents across BigQuery, Snowflake, and Databricks" readme = "README.md" requires-python = ">=3.12" license = "MIT" dependencies = [ "mcp>=2.0.0", "google-cloud-bigquery>=3.25.0", "google-cloud-bigquery-reservation>=1.15.0", "snowflake-connector-python>=4.7.1", "databricks-sql-connector>=4.0.0", "databricks-sdk>=0.20.0", "pydantic>=2.9.0", ] [project.scripts] cost-guard-mcp = "cost_guard_mcp.server:main" [dependency-groups] dev = [ "pytest>=8.3.0", "pytest-asyncio>=0.24.0", "pytest-cov>=5.0.0", "ruff>=0.7.0", "mypy>=1.14.0", ] # Opt-in only - see server.py's _bootstrap_opentelemetry(). `opentelemetry-api` is already # a transitive dependency of `mcp` itself (its OpenTelemetryMiddleware ships on by default # for every server, per mcp/server/lowlevel/server.py - just a documented no-op until a # TracerProvider with a real exporter is registered as the global provider). This group # adds only what that registration itself needs - the SDK and an OTLP exporter - so a # deployment that never sets OTEL_EXPORTER_OTLP_ENDPOINT never needs to install it. otel = [ "opentelemetry-sdk>=1.27.0", "opentelemetry-exporter-otlp-proto-grpc>=1.27.0", ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/cost_guard_mcp"] [tool.pytest.ini_options] testpaths = ["tests/unit"] asyncio_mode = "auto" [tool.ruff] line-length = 100 target-version = "py312" [tool.ruff.lint] # Ruff's defaults (E4, E7, E9, F) plus flake8-bandit (S) for security linting - # ruff is a linter, not a type checker, and its own docs say to pair it with # one; see [tool.mypy] below. extend-select = ["S"] [tool.ruff.lint.per-file-ignores] # S101 (assert) is how pytest tests are supposed to work; S105/S106/S108 # (hardcoded password/temp-file patterns) are all fake fixture data in tests # (mocked env vars, obviously-fake passwords like "hunter2") - none of these # findings are real in test code, only in src/. "tests/**" = ["S101", "S105", "S106", "S108"] [tool.mypy] plugins = ["pydantic.mypy"] python_version = "3.12" disallow_untyped_defs = true warn_unused_ignores = true warn_redundant_casts = true