[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "kepler-mcp-gitlab-server"
version = "0.1.0"
description = "GitLab MCP Server - Provides GitLab integration tools for Model Context Protocol"
readme = "README.md"
license = "MIT"
requires-python = ">=3.12"
authors = [
{name = "Kepler Team"}
]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Software Development :: Libraries :: Python Modules",
]
dependencies = [
"fastmcp>=0.1.0",
"pydantic>=2.0.0",
"typer>=0.9.0",
"httpx>=0.25.0",
"authlib>=1.2.0",
"python-dotenv>=1.0.0",
"cryptography>=41.0.0",
"starlette>=0.32.0",
"uvicorn>=0.24.0",
]
[project.optional-dependencies]
dev = [
# Static analysis and formatting
"ruff>=0.1.6",
"mypy>=1.7.0",
"bandit>=1.7.6",
"safety>=2.3.5",
"types-PyYAML>=6.0.0",
# Testing
"pytest>=7.4.0",
"pytest-asyncio>=0.21.0",
"pytest-httpx>=0.28.0",
"pytest-cov>=4.1.0",
"coverage>=7.3.0",
"respx>=0.20.0",
]
[project.scripts]
kepler-mcp-gitlab = "kepler_mcp_gitlab.cli:main"
[project.urls]
Homepage = "https://github.com/ryan-rbw/kepler-mcp-gitlab-server"
Repository = "https://github.com/ryan-rbw/kepler-mcp-gitlab-server"
Documentation = "https://github.com/ryan-rbw/kepler-mcp-gitlab-server#readme"
[tool.setuptools.packages.find]
where = ["src"]
[tool.ruff]
target-version = "py312"
line-length = 100
src = ["src", "tests"]
[tool.ruff.lint]
select = [
# Core Python checks
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # Pyflakes
"I", # isort
# Code quality
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
"SIM", # flake8-simplify
"PTH", # flake8-use-pathlib
"ERA", # eradicate (commented code)
"PL", # Pylint
"RUF", # Ruff-specific rules
# Type checking optimization
"TCH", # flake8-type-checking
# Security
"S", # flake8-bandit (security)
# Naming conventions
"N", # pep8-naming
# Type annotations
"ANN", # flake8-annotations
# Built-in shadowing
"A", # flake8-builtins
# Datetime handling
"DTZ", # flake8-datetimez
# Debugger detection
"T10", # flake8-debugger
# String concatenation
"ISC", # flake8-implicit-str-concat
# Code smells
"PIE", # flake8-pie
# Return statements
"RET", # flake8-return
# Performance
"PERF", # perflint
# Unused arguments (enabled, but with specific ignores)
"ARG", # flake8-unused-arguments
]
ignore = [
# ============================================================
# LEGITIMATE PROJECT-SPECIFIC IGNORES (documented reasons)
# ============================================================
"B008", # Function call in default argument - intentional for typer.Option()
"PLR0913", # Too many arguments - complex configs need many params
"PLR2004", # Magic value comparison - acceptable in tests and configs
# ============================================================
# THIRD-PARTY LIBRARY LIMITATIONS
# These would be fixed if we controlled the library
# ============================================================
"ANN401", # Dynamically typed Any - required for Pydantic validators and FastMCP
# ============================================================
# TEST-SPECIFIC IGNORES (applied via per-file-ignores below)
# ============================================================
# S101 (assert) - handled in per-file-ignores for tests only
]
[tool.ruff.lint.per-file-ignores]
# Tests are allowed to use assert statements and hardcoded test credentials
"tests/**/*.py" = [
"S101", # assert is standard in pytest
"S104", # Binding to 0.0.0.0 in test assertions
"S105", # Hardcoded password - test fixtures need fake credentials
"S106", # Hardcoded password in function argument - test fixtures
"ARG001", # Unused function argument - pytest fixtures
"PLR2004", # Magic value comparison - test assertions
"PLC0415", # Lazy imports in test functions - common pattern
]
# CLI module uses typer patterns and lazy imports for startup performance
"src/kepler_mcp_gitlab/cli.py" = [
"ARG001", # Unused argument - typer callback signatures
"PLC0415", # Lazy imports - intentional for CLI startup performance
]
# Server module uses lazy imports to avoid circular dependencies
"src/kepler_mcp_gitlab/server.py" = [
"PLC0415", # Lazy imports - intentional to avoid circular imports
]
# Transport module has Starlette handlers with unused request params
"src/kepler_mcp_gitlab/transport.py" = [
"ARG001", # Unused request param - required by Starlette handler signature
"PLC0415", # Lazy uvicorn import - not needed until SSE mode runs
"PLR0915", # Long create_sse_app function - acceptable for transport setup
]
# Config module has lazy json/yaml imports for optional dependencies
"src/kepler_mcp_gitlab/config.py" = [
"PLC0415", # Lazy yaml import - optional dependency
]
# Logging module uses global singleton pattern (standard for logging config)
"src/kepler_mcp_gitlab/logging_config.py" = [
"PLW0603", # Global statement - standard singleton pattern for logging
]
# OAuth flows has false positive for token_type field
"src/kepler_mcp_gitlab/oauth/flows.py" = [
"S105", # False positive - "Bearer" is a token type constant, not a password
]
# Tools base module has lazy asyncio import and decorator description param
"src/kepler_mcp_gitlab/tools/base.py" = [
"ARG001", # description param - reserved for future FastMCP integration
"PLC0415", # Lazy asyncio import - for async detection at runtime
]
# Info tools has lazy fastmcp import for version detection
"src/kepler_mcp_gitlab/tools/info.py" = [
"PLC0415", # Lazy fastmcp import - version detection at runtime
]
[tool.ruff.lint.isort]
known-first-party = ["kepler_mcp_gitlab"]
[tool.ruff.lint.flake8-annotations]
# Allow Any for self/cls in methods (standard practice)
allow-star-arg-any = true
# Suppress ANN101/ANN102 for self/cls
suppress-none-returning = true
[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_ignores = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_configs = true
show_error_codes = true
show_column_numbers = true
pretty = true
[[tool.mypy.overrides]]
module = [
"fastmcp.*",
"authlib.*",
]
ignore_missing_imports = true
# FastMCP's @app.tool() decorator returns untyped callables
# These modules use FastMCP tools extensively
[[tool.mypy.overrides]]
module = [
"kepler_mcp_gitlab.tools.*",
"kepler_mcp_gitlab.application",
]
disallow_untyped_decorators = false
[tool.bandit]
exclude_dirs = ["tests", "scripts"]
skips = ["B101"] # assert_used - OK in tests
[tool.pytest.ini_options]
minversion = "7.0"
asyncio_mode = "auto"
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-v",
"--tb=short",
"--strict-markers",
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow tests",
]
[tool.coverage.run]
source = ["src/kepler_mcp_gitlab"]
branch = true
omit = ["*/tests/*", "*/__pycache__/*"]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise NotImplementedError",
"if TYPE_CHECKING:",
"if __name__ == .__main__.:",
]
fail_under = 80
show_missing = true