[project] name = "a2atlassian" version = "0.5.1" description = "Agent-to-Atlassian — CLI and MCP server for AI agents to work with Jira & Confluence." readme = "README.md" requires-python = ">=3.12" license = "Apache-2.0" authors = [{name = "Denis Tomilin"}] keywords = ["mcp", "mcp-server", "model-context-protocol", "atlassian", "jira", "confluence", "agent", "ai", "llm"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries", "Framework :: AsyncIO", ] dependencies = [ "click>=8,<9", "mcp[cli]>=1.9,<2", "atlassian-python-api>=4,<5", "httpx>=0.27,<1", "toon-format>=0.1,<1", "tomli-w>=1,<2", "pydantic>=2,<3", "markdown-it-py>=3,<4", "mdit-py-plugins>=0.4,<1", ] [project.scripts] a2atlassian = "a2atlassian.cli:cli" a2atlassian-mcp = "a2atlassian.mcp_server:main" [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/a2atlassian"] [tool.ruff] target-version = "py312" line-length = 140 output-format = "concise" [tool.ruff.lint] select = [ "F", "S", "T10", "T20", "BLE", "PGH", "E", "W", "I", "N", "UP", "C4", "PIE", "TC", "PTH", "FURB", "RUF", "B", "A", "DTZ", "ISC", "RET", "SIM", "ARG", "PERF", "LOG", "G", "SLF", "TID", "PL", "C90", "EM", "FBT", "PT", ] ignore = [ "SIM108", "SIM110", "RUF001", "RUF015", "EM101", "EM102", "FBT001", "FBT002", "PLR0913", "PLR2004", "ARG001", "A003", "PT001", "PT023", "PERF203", "RET504", "PLW2901", "SLF001", ] [tool.ruff.lint.mccabe] max-complexity = 10 [tool.ruff.lint.pylint] max-args = 8 max-statements = 50 max-branches = 10 max-returns = 6 [tool.ruff.lint.per-file-ignores] "tests/**" = [ "S101", "S105", "S106", "E402", "ARG001", "PLR2004", "SLF001", "PT011", "PLR0915", "PLC0415", ] "src/a2atlassian/jira_read_tools.py" = ["C901", "PLR0915"] "src/a2atlassian/jira_write_tools.py" = ["C901", "PLR0915"] "scripts/**" = ["T201", "BLE001", "C901", "PLR0912", "PLR0915"] [tool.pytest.ini_options] testpaths = ["tests"] addopts = "-v --strict-markers --cov --cov-report=term:skip-covered --cov-report=xml --cov-fail-under=90" asyncio_mode = "auto" markers = [ "integration: marks tests that hit a real Jira instance (use --integration to run)", ] env = [ "A2ATLASSIAN_TEST=1", ] [tool.coverage.run] source = ["src/a2atlassian"] branch = true omit = ["src/a2atlassian/cli.py", "src/a2atlassian/mcp_server.py", "src/a2atlassian/jira_read_tools.py", "src/a2atlassian/jira_write_tools.py"] [tool.coverage.report] show_missing = false skip_covered = true exclude_lines = [ "pragma: no cover", "if __name__ == .__main__.", "if TYPE_CHECKING:", "class .*\\bProtocol\\):", "\\.\\.\\.", ] [dependency-groups] dev = [ "pytest>=8", "pytest-cov>=6", "diff-cover>=9", "ruff>=0.9", "pytest-env>=1.6.0", "pytest-asyncio>=0.24", "pytest-xdist>=3.6", "pytest-timeout>=2.4", "pytest-recording>=0.13", "ty>=0.0.28", ] [tool.ty.src] exclude = ["tests/"]