[project] name = "plesk-mcp" version = "0.1.1" description = "Plesk MCP server" readme = "README.md" license = "MIT" license-files = ["LICENSE"] authors = [ { name = "Flayed One" } ] keywords = ["plesk", "mcp", "model-context-protocol", "llm", "automation", "hosting", "wp-toolkit"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Customer Service", "Intended Audience :: Developers", "Intended Audience :: System Administrators", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Topic :: System :: Systems Administration", ] requires-python = ">=3.10" dependencies = [ "async-lru", "fastmcp>=3", "httpx", ] [dependency-groups] dev = [ "mypy", "pip", "pytest", "pytest-asyncio", "respx", "ruff", ] [build-system] requires = ["uv_build>=0.10,<0.12"] build-backend = "uv_build" [project.scripts] plesk-mcp = "plesk_mcp.server:main" [project.urls] Homepage = "https://github.com/FlayedOne/plesk-mcp" Repository = "https://github.com/FlayedOne/plesk-mcp" Issues = "https://github.com/FlayedOne/plesk-mcp/issues" Changelog = "https://github.com/FlayedOne/plesk-mcp/blob/master/CHANGELOG.md" [tool.uv] exclude-newer = "7 days" constraint-dependencies = [ # requests 2.32 compatibility "chardet<6", ] [[tool.uv.index]] # uv publish --index testpypi # uvx --index https://test.pypi.org/simple/ --index-strategy unsafe-best-match plesk-mcp name = "testpypi" url = "https://test.pypi.org/simple/" publish-url = "https://test.pypi.org/legacy/" explicit = true [tool.ruff] line-length = 140 target-version = "py310" [tool.ruff.lint] select = [ "E", # pycodestyle errors (not overlapping formatter: E4, E7, E9) "W", # pycodestyle warnings "D", # pydocstyle "F", # Pyflakes "I", # isort (import sorting) "ASYNC", # flake8-async "B", # flake8-bugbear "C4", # flake8-comprehensions "COM", # flake8-commas "DTZ", # flake8-datetimez "EXE", # flake8-executable "ICN", # flake8-import-conventions "ISC", # flake8-implicit-str-concat "N", # pep8-naming "PIE", # flake8-pie "PL", # Pylint "PT", # flake8-pytest-style "RSE", # flake8-raise "RUF", # Ruff-specific rules "S", # flake8-bandit "T10", # flake8-debugger "UP", # pyupgrade ] ignore = [ "W191", "E111", "E114", "E117", "D206", "D300", "Q", "COM812", "COM819", "ISC002", # formatter compatibility "S101", # allow asserts ] [tool.ruff.lint.per-file-ignores] "__init__.py" = [ "D104", # allow missing docstrings ] "**/tests/**" = [ "D", # don't require docstrings in tests "PLR2004", # magic value comparisons are fine in assertions "S105", "S106", "S108", # hardcoded credentials and tmp paths are expected (test fixtures) ] [tool.ruff.lint.isort] default-section = "first-party" force-to-top = ["pytest"] known-third-party = [ "async_lru", "chromadb", "fastmcp", "httpx", "mcp", "platformdirs", ] [tool.ruff.lint.pycodestyle] max-doc-length = 140 [tool.ruff.lint.pydocstyle] convention = "google" [tool.ruff.format] docstring-code-format = true quote-style = "preserve" skip-magic-trailing-comma = false [tool.mypy] python_version = "3.10" sqlite_cache = true extra_checks = true strict_equality = true warn_no_return = true warn_redundant_casts = true warn_return_any = true warn_unreachable = true warn_unused_configs = true warn_unused_ignores = true check_untyped_defs = true disallow_incomplete_defs = true disallow_untyped_calls = true disallow_untyped_defs = true follow_imports = "normal" ignore_missing_imports = true explicit_package_bases = true namespace_packages = true exclude = [ # Each sub-project is an independent package - checked separately by its CI job. "(^|/)(local-docs|remote-docs|tmp)/", ] pretty = true show_column_numbers = true show_error_codes = true show_error_context = true [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] markers = [ "smoke: opt-in tests that exercise real endpoints (require live services and credentials)", ] addopts = "-ra --strict-markers -m 'not smoke'"