[project] name = "couchbase-mcp-server" version = "1.0.2rc4" description = "Couchbase MCP Server - Enable AI agents to connect to and interact with Couchbase clusters." readme = "README.md" requires-python = ">=3.10,<3.15" license = "Apache-2.0" authors = [ { name="Couchbase, Inc.", email="mcp-server@couchbase.com" }, ] classifiers = [ "Development Status :: 5 - Production/Stable", "Programming Language :: Python :: 3", "Topic :: Database", ] dependencies = [ "click>=8.2.1,<9.0.0", "couchbase>=4.4.0,<5.0.0", "lark-sqlpp>=0.2.1", "fastmcp>=3.2.0,<4.0.0", "reo-census>=0.1.3,<0.2.0", # Fuzzy matching for discover_tool_input_values. Upper bound is deliberate: rapidfuzz 3.14.6 # raised requires-python to >=3.11, which would silently break this project's 3.10 support. "rapidfuzz>=3.13.0,<3.14.6", ] [project.urls] Homepage = "https://github.com/couchbase/mcp-server-couchbase" Documentation = "https://docs.couchbase.com/mcp-server/get-started/overview.html" Issues = "https://github.com/couchbase/mcp-server-couchbase/issues" [project.scripts] couchbase-mcp-server = "mcp_server:main" # Development dependencies [project.optional-dependencies] dev = [ "ruff==0.16.0", "pre-commit==4.6.1", "pytest==9.1.1", "pytest-asyncio==1.4.0", "pytest-cov>=7.0.0", "openai>=2.0.0,<3.0.0", ] # Ruff configuration [tool.ruff] # Set the line length to match Black's default line-length = 88 target-version = "py310" # Include and exclude patterns include = ["src/**/*.py", "*.py"] exclude = [ ".bzr", ".direnv", ".eggs", ".git", ".git-rewrite", ".hg", ".ipynb_checkpoints", ".mypy_cache", ".nox", ".pants.d", ".pyenv", ".pytest_cache", ".pytype", ".ruff_cache", ".svn", ".tox", ".venv", "__pypackages__", "_build", "buck-out", "build", "dist", "node_modules", "site-packages", "venv", ] [tool.ruff.lint] # Enable specific rule categories select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # Pyflakes "UP", # pyupgrade "B", # flake8-bugbear "SIM", # flake8-simplify "I", # isort "N", # pep8-naming "C4", # flake8-comprehensions "PIE", # flake8-pie "PL", # Pylint "RUF", # Ruff-specific rules "S", # flake8-bandit ] # Disable specific rules that might be too strict for your project ignore = [ "E501", # Line too long (handled by formatter) "PLR0913", # Too many arguments "PLR0917", # Too many positional arguments "PLR2004", # Magic value used in comparison "N806", # Variable in function should be lowercase (for SQL++ variables) "RUF022", # __all__ is not sorted ] # Allow fix for all enabled rules (when `--fix`) is provided. fixable = ["ALL"] unfixable = [] # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" [tool.ruff.lint.per-file-ignores] # Tests can use magic values and have longer names # S101: assert is the standard pytest idiom, not a security issue here. # S106/S108: dummy credentials and /tmp paths in test fixtures, not real secrets. # S110/S112/S603/S607: intentional except-pass/continue in skip logic and # subprocess calls with hardcoded (not attacker-controlled) arguments. # S608: SQL++ query strings built from trusted, hardcoded test fixture values. "test_*.py" = [ "PLR2004", "N802", "S101", "S106", "S108", "S110", "S112", "S603", "S607", "S608", ] # conftest.py/_harness.py helpers use the same trusted subprocess/except-pass/ # assert patterns as tests. "conftest.py" = ["S112", "S607"] "_harness.py" = ["S101"] # Config files can have longer names "**/config.py" = ["N802"] # Dev-only data-seeding script: queries/URLs are built from internal, # hardcoded values, not attacker-controlled input. "scripts/setup_test_data.py" = ["S110", "S310", "S608"] [tool.ruff.lint.isort] # Organize imports known-first-party = ["cb_mcp", "providers"] split-on-trailing-comma = true [tool.ruff.format] # Format configuration quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto" # Pytest configuration [tool.pytest.ini_options] asyncio_mode = "strict" asyncio_default_fixture_loop_scope = "function" # Put tests/ on sys.path so shared helpers (tests/_test_env.py) are importable # from any subdirectory (tests/unit, tests/integration, tests/accuracy). pythonpath = ["tests"] markers = [ "integration: Integration tests against a live Couchbase cluster via the MCP server.", "accuracy: AI-in-the-loop accuracy tests. Require OPENAI_API_KEY and a Couchbase cluster.", "result_eval: LLM-as-judge answer-correctness evals. Require OPENAI_API_KEY and a Couchbase cluster.", "perf: In-process performance tests. Opt-in via CB_MCP_PERF=1; not run in CI.", ] # Build system configuration [build-system] requires = ["hatchling"] build-backend = "hatchling.build" # Configure hatchling to use src-layout with the cb_mcp reusable package, # the standalone-host providers package, and the top-level mcp_server.py CLI # script (kept for "uv run src/mcp_server.py" workflows). [tool.hatch.build.targets.wheel] packages = ["src/cb_mcp", "src/providers"] [tool.hatch.build.targets.wheel.force-include] "src/mcp_server.py" = "mcp_server.py" [tool.uv] package = true