[project] name = "mcp-pinot-server" version = "5.0.0" description = "A production-grade MCP server for Apache Pinot" readme = "README.md" license = "Apache-2.0" requires-python = ">=3.12" authors = [{ name = "StarTree" }] keywords = ["apache-pinot", "analytics", "mcp", "model-context-protocol"] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Programming Language :: Python :: 3.12", "Topic :: Database :: Front-Ends", ] dependencies = [ "mcp[cli]>=2.3.0,<3", "fastmcp==4.1.2", "pinotdb>=9.2.1,<10", "uvicorn[standard]>=0.35.0", "python-dotenv>=1.2.2", "httpx>=0.27.2", "requests>=2.33.0", "rpds-py>=0.18.1", "pydantic>=2.12.5", "pyyaml>=6.0.1", "sqlglot>=30.8.0", ] [project.scripts] mcp-pinot = "mcp_pinot.server:main" # Built-in auth providers. Downstream forks can add their own provider by # declaring an entry point in this group without modifying upstream code. [project.entry-points."mcp_pinot.auth_providers"] oauth = "mcp_pinot.auth.oauth:build_oauth_auth" [project.urls] Homepage = "https://github.com/startreedata/mcp-pinot" Documentation = "https://startreedata.github.io/mcp-pinot/" Repository = "https://github.com/startreedata/mcp-pinot.git" Issues = "https://github.com/startreedata/mcp-pinot/issues" Changelog = "https://github.com/startreedata/mcp-pinot/blob/main/CHANGELOG.md" [project.optional-dependencies] dev = [ "pytest>=9.0.3", "pytest-asyncio", "pytest-mock", "pytest-cov", "ruff>=0.1.6", "mypy>=1.11", ] [build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" [tool.setuptools] packages = ["mcp_pinot", "mcp_pinot.auth"] [tool.setuptools.package-data] mcp_pinot = ["py.typed"] [tool.pytest.ini_options] testpaths = ["tests"] pythonpath = ["."] python_files = ["test_*.py"] python_classes = ["Test*"] python_functions = ["test_*"] norecursedirs = ["lib", ".git", ".tox", "dist", "build", "*.egg"] markers = [ "asyncio: mark test as an async test", ] addopts = [ "-v", "--tb=short", "--strict-markers", ] [tool.ruff] target-version = "py312" line-length = 88 src = ["mcp_pinot"] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # Pyflakes "I", # isort "S", # bandit security "B", # flake8-bugbear "UP", # pyupgrade "C4", # flake8-comprehensions "SIM", # flake8-simplify "RUF", # Ruff-specific rules ] ignore = [ # Development necessities "S104", # bind all interfaces (dev servers) "S108", # temp files (testing) "SIM117", # nested with-statements are clearer than combined ones here ] [tool.ruff.lint.per-file-ignores] "tests/*" = [ "S101", # assert statements "S105", # hardcoded passwords in test fixtures "S106", # hardcoded passwords in fixtures "S108", # temp files ] "simple_query_builtin.py" = [ "S310", # URL open for demo/testing purposes ] "examples/*" = [ "S310", # URL open for demo/testing purposes ] "test_http_with_server.py" = [ "S310", # URL open for demo/testing purposes ] "tests/test_http_live.py" = [ "S310", # URL open for testing purposes ] "tests/test_service/*" = [ "S310", # URL open for integration testing "S110", # try-except-pass for connection retries ] [tool.ruff.lint.isort] known-first-party = ["mcp_pinot"] force-sort-within-sections = true split-on-trailing-comma = true [tool.ruff.format] quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto" [tool.mypy] python_version = "3.12" files = ["mcp_pinot"] ignore_missing_imports = true no_implicit_optional = true check_untyped_defs = true disallow_incomplete_defs = true warn_redundant_casts = true warn_unused_configs = true [tool.coverage.run] source = ["mcp_pinot"] [tool.coverage.report] show_missing = true fail_under = 85 [tool.uv.workspace] members = [ "mcp-pinot", ] [dependency-groups] dev = [ "pytest>=9.0.3", "pytest-asyncio>=0.26.0", "pytest-cov>=6.1.1", "pytest-mock>=3.14.0", "ruff>=0.12.0", "mypy>=1.11", ]