Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 24 additions & 19 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,30 @@ Our Ruff configuration includes:
```
mcp-server-couchbase/
├── src/
│ ├── mcp_server.py # MCP server entry point
│ ├── tools/ # MCP tool implementations
│ │ ├── __init__.py # Tool exports and ALL_TOOLS list
│ │ ├── server.py # Server status and connection tools
│ │ ├── kv.py # Key-value operations (CRUD)
│ │ └── query.py # SQL++ query operations
│ └── utils/ # Utility modules
│ ├── __init__.py # Utility exports
│ ├── constants.py # Project constants
│ ├── config.py # Configuration management
│ ├── connection.py # Couchbase connection handling
│ └── context.py # Application context management
├── scripts/ # Development scripts
│ ├── lint.sh # Manual linting script
│ └── lint_fix.sh # Auto-fix linting issues
├── .pre-commit-config.yaml # Pre-commit hook configuration
├── pyproject.toml # Project dependencies and Ruff config
├── CONTRIBUTING.md # Contribution Guide
└── README.md # Usage
│ ├── mcp_server.py # MCP server entry point
│ ├── certs/ # SSL/TLS certificates
│ │ ├── __init__.py # Package marker
│ │ └── capella_root_ca.pem # Capella root CA certificate (for Capella connections)
│ ├── tools/ # MCP tool implementations
│ │ ├── __init__.py # Tool exports and ALL_TOOLS list
│ │ ├── server.py # Server status and connection tools
│ │ ├── kv.py # Key-value operations (CRUD)
│ │ ├── query.py # SQL++ query operations
│ │ └── index.py # Index operations and recommendations
│ └── utils/ # Utility modules
│ ├── __init__.py # Utility exports
│ ├── constants.py # Project constants
│ ├── config.py # Configuration management
│ ├── connection.py # Couchbase connection handling
│ ├── context.py # Application context management
│ └── index_utils.py # Index-related helper functions
├── scripts/ # Development scripts
│ ├── lint.sh # Manual linting script
│ └── lint_fix.sh # Auto-fix linting issues
├── .pre-commit-config.yaml # Pre-commit hook configuration
├── pyproject.toml # Project dependencies and Ruff config
├── CONTRIBUTING.md # Contribution Guide
└── README.md # Usage
```

## 🛠️ Development Workflow
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ENV UV_COMPILE_BYTECODE=1 \
WORKDIR /build

# Copy dependency files for caching
COPY pyproject.toml ./
COPY pyproject.toml README.md ./
COPY src/ ./src/

# Create virtual environment and install dependencies
Expand Down
20 changes: 19 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "couchbase-mcp-server"
version = "0.5.0"
description = "Couchbase MCP Server - The Developer Data Platform for Critical Applications in Our AI World"
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.10,<3.14"
license = "Apache-2.0"
authors = [
{ name="Nithish Raghunandanan", email="devadvocates@couchbase.com" },
Expand Down Expand Up @@ -124,5 +124,23 @@ indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

# Build system configuration
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

# Configure hatchling to use src-layout
[tool.hatch.build.targets.wheel]
# Include all packages from src/ and map them to the root
only-include = [
"src/mcp_server.py",
"src/tools",
"src/utils",
"src/certs"
]

[tool.hatch.build.targets.wheel.sources]
"src" = ""

[tool.uv]
package = true
Empty file added src/certs/__init__.py
Empty file.
File renamed without changes.
29 changes: 24 additions & 5 deletions src/utils/index_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import logging
import os
from importlib.resources import files
from typing import Any
from urllib.parse import urlparse

Expand Down Expand Up @@ -87,14 +88,32 @@ def process_index_data(
def _get_capella_root_ca_path() -> str:
"""Get the path to the Capella root CA certificate.

Uses importlib.resources to locate the certificate file, which works when the package is installed with fallback for development.

Returns:
Path to the Capella root CA certificate file.
"""
# Get the path to the certs directory relative to this file
utils_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(os.path.dirname(utils_dir))
capella_ca_path = os.path.join(project_root, "certs", "capella_root_ca.pem")
return capella_ca_path
try:
# Use importlib.resources to get the certificate path (works for installed packages)
cert_file = files("certs").joinpath("capella_root_ca.pem")
# Convert to string path - this works for both installed packages and dev mode
return str(cert_file)
except (ImportError, FileNotFoundError, TypeError):
# Fallback for development: use src/certs/ directory
utils_dir = os.path.dirname(os.path.abspath(__file__))
src_dir = os.path.dirname(utils_dir)
fallback_path = os.path.join(src_dir, "certs", "capella_root_ca.pem")

if os.path.exists(fallback_path):
logger.info(f"Using fallback certificate path: {fallback_path}")
return fallback_path

# If we still can't find it, log a warning and return the fallback path anyway
logger.warning(
f"Could not locate Capella root CA certificate at {fallback_path}. "
"SSL verification may fail for Capella connections."
)
return fallback_path


def _extract_host_from_connection_string(connection_string: str) -> str:
Expand Down
Loading