[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "intervalsicu-mcp" version = "0.1.0" description = "A Model Context Protocol server for Intervals.icu (FastMCP, native OAuth)" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.12" license = { text = "GPL-3.0-only" } authors = [{ name = "Marc Vilanova", email = "barker-riddle.8z@icloud.com" }] dependencies = [ "mcp[cli]>=1.28.1", "httpx>=0.25.0", "python-dotenv>=1.0.0", "pyjwt[crypto]>=2.8.0", "sqlalchemy[asyncio]>=2.0.30", "asyncpg>=0.29", "alembic>=1.13", ] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.12", "Topic :: Software Development :: Libraries", ] keywords = ["intervals", "cycling", "running", "mcp", "ai"] [project.urls] "Homepage" = "https://git.farh.net/farhoodlabs/intervalsicu-mcp" "Bug Tracker" = "https://git.farh.net/farhoodlabs/intervalsicu-mcp/issues" "Upstream" = "https://github.com/mvilanova/intervals-mcp-server" [project.optional-dependencies] dev = ["pytest>=8.3.5", "mypy>=1.0.0", "ruff>=0.1.0", "pytest-asyncio>=0.21", "pre-commit", "hatch", "pytest-mock==3.12.0", "pytest-cov>=5.0", "cryptography>=42.0", "aiosqlite>=0.20"] [tool.hatch.build] include = ["server.py", "utils/*.py", "README.md", ".env.example"] [tool.hatch.build.targets.wheel] packages = ["src/intervals_mcp_server"] [tool.hatch.envs.default.scripts] test = "pytest -q" [tool.ruff] # Exclude a variety of commonly ignored directories. exclude = [ ".bzr", ".direnv", ".eggs", ".git", ".hg", ".mypy_cache", ".nox", ".pants.d", ".ruff_cache", ".svn", ".tox", ".venv", "__pypackages__", "_build", "buck-out", "build", "dist", "node_modules", "venv", ] line-length = 100 target-version = "py311" [tool.ruff.lint] # Select specific errors and warnings select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes # "I", # isort "C", # flake8-comprehensions "B", # flake8-bugbear ] # Ignore specific errors and warnings ignore = [ "E501", # line too long, handled by black "B008", # do not perform function calls in argument defaults "C901", # complexity "G004", # Ignore f-string in logging ] # Allow autofix for all enabled rules (when `--fix`) is provided. fixable = ["A", "B", "C", "D", "E", "F"] # No unfixable rules. unfixable = [] # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" isort.known-third-party = ["starlette"] # Unlike Flake8, default to a complexity level of 10. mccabe.max-complexity = 10 [tool.pylint.design] max-args = 8 max-positional-arguments = 8 [tool.typos] default.check-filename = true default.check-file = true default.unicode = true default.locale = "en-us" [tool.pytest.ini_options] addopts = "-q --cov=intervals_mcp_server --cov-report=term-missing --cov-fail-under=90" testpaths = ["tests"] python_files = "test_*.py" asyncio_default_fixture_loop_scope = "function" [tool.uv] index-url = "https://pypi.org/simple" # Semantic versioning via Commitizen (conventional commits). Source of truth is the # [project].version above. Bump + changelog + tag with: uvx --from commitizen cz bump # (feat -> minor, fix -> patch; pre-1.0 so breaking changes stay in 0.x). Tags are vX.Y.Z. [tool.commitizen] name = "cz_conventional_commits" version_provider = "pep621" tag_format = "v$version" major_version_zero = true update_changelog_on_bump = true changelog_file = "CHANGELOG.md"