Contributing
Welcome to the MXCP development community! This guide helps you contribute to the project.
Your First Contribution
Section titled “Your First Contribution”New to MXCP? Here’s how to get started:
- Find an issue - Look for issues labeled
good first issueorhelp wanted - Comment on the issue - Let maintainers know you’re working on it
- Fork and clone - Set up your development environment
- Make your changes - Follow the guidelines below
- Submit a PR - Request review from maintainers
Common contribution types:
- Bug fixes - Fix issues reported by users
- Documentation - Improve guides, fix typos, add examples
- Features - Add new functionality (discuss first in an issue)
- Tests - Improve test coverage
Development Setup
Section titled “Development Setup”Prerequisites
Section titled “Prerequisites”- Python 3.11 or higher
- Git
- GitHub account
- Basic understanding of SQL and YAML
uvpackage manager
Installation
Section titled “Installation”-
Fork and clone:
Terminal window git clone https://github.com/YOUR_USERNAME/mxcp.gitcd mxcp -
Install dependencies:
Terminal window # Install uv if you haven't alreadypip install uv# Install with dev dependenciesuv pip install -e ".[dev]"uvautomatically manages the virtual environment - no need to create one manually. -
Install optional features (for testing specific integrations):
Terminal window # Test Vault integrationuv pip install -e ".[dev,vault]"# Test 1Password integrationuv pip install -e ".[dev,onepassword]"# Everything (all optional features + dev tools)uv pip install -e ".[all]"
Project Structure
Section titled “Project Structure”mxcp/├── src/mxcp/ # Main package│ ├── plugins/ # Plugin system│ ├── runtime/ # Runtime initialization│ ├── sdk/ # Core SDK modules│ │ ├── audit/ # Audit logging│ │ ├── auth/ # Authentication│ │ ├── core/ # Core utilities│ │ ├── duckdb/ # DuckDB execution engine│ │ ├── evals/ # Evaluations│ │ ├── executor/ # Query execution│ │ ├── mcp/ # MCP protocol│ │ ├── policy/ # Policy enforcement│ │ ├── telemetry/ # Telemetry│ │ └── validator/ # Validation│ └── server/ # MCP server│ ├── interfaces/│ │ ├── cli/ # CLI commands│ │ └── server/ # HTTP/SSE server│ ├── definitions/ # Endpoint definitions│ └── services/ # Business logic├── tests/ # Test suite│ └── server/fixtures/ # Test repositories├── docs/ # Documentation└── examples/ # Example projectsDevelopment Workflow
Section titled “Development Workflow”1. Branch Management
Section titled “1. Branch Management”# Create feature branchgit checkout -b feature/your-feature-name
# Or bugfix branchgit checkout -b fix/your-bugfix-name
# Keep up to date with maingit fetch origingit rebase origin/main2. Code Style
Section titled “2. Code Style”MXCP enforces code quality with automated tools:
- black: Code formatting (line-length=100)
- ruff: Linting and import sorting
- mypy: Static type checking
Guidelines:
- Follow PEP 8 (enforced by black and ruff)
- Use type hints for all function parameters and return values
- Write docstrings for all public functions and classes
- Keep lines under 100 characters
- Use meaningful variable and function names
# Check all (recommended before committing)./check-all.sh
# Auto-fix formatting./format-all.shIndividual tools:
# Ruff - check for issuesuv run ruff check .
# Ruff - auto-fix issuesuv run ruff check . --fix
# Ruff - show diff without changinguv run ruff check . --diff
# Black - format codeuv run black .
# Black - check without changinguv run black . --check --diff
# Mypy - type checkinguv run mypy .3. Testing
Section titled “3. Testing”# Run all testsuv run pytest
# Run specific test fileuv run pytest tests/test_cli_lint.py
# Run tests matching a patternuv run pytest -k "test_format"
# With coverageuv run pytest --cov=mxcp
# Verbose outputuv run pytest -v4. Documentation
Section titled “4. Documentation”- Update relevant docs when adding features
- Add docstrings to new functions and classes
- Update examples if affected by your changes
- Follow existing documentation style
Test Fixtures
Section titled “Test Fixtures”Each test has its own complete repository fixture. This ensures test isolation and reproducibility.
For endpoint testing best practices, see the Testing Guide.
Fixture Structure
Section titled “Fixture Structure”tests/├── server/│ ├── fixtures/│ │ ├── test-repo/ # Example fixture directory│ │ │ ├── mxcp-site.yml # Site configuration│ │ │ ├── mxcp-config.yml # User configuration│ │ │ ├── tools/ # Tool definitions│ │ │ ├── resources/ # Resource definitions│ │ │ ├── prompts/ # Prompt definitions│ │ │ ├── evals/ # Evaluation definitions│ │ │ ├── python/ # Python endpoints│ │ │ ├── plugins/ # MXCP plugins│ │ │ ├── sql/ # SQL files│ │ │ ├── drift/ # Drift snapshots│ │ │ └── audit/ # Audit logs│ │ └── validation/ # Another fixture│ │ └── ...│ ├── test_cli.py│ └── test_validation.py├── sdk/ # SDK tests└── conftest.py # Shared fixturesTest Pattern
Section titled “Test Pattern”@pytest.fixture(scope="session", autouse=True)def set_mxcp_config_env(): """Point to test-specific config file.""" os.environ["MXCP_CONFIG"] = str( Path(__file__).parent / "fixtures" / "test-repo" / "mxcp-config.yml" )
@pytest.fixturedef test_repo_path(): """Path to the test repository fixture.""" return Path(__file__).parent / "fixtures" / "test-repo"
@pytest.fixturedef test_config(test_repo_path): """Load test configuration with proper chdir.""" original_dir = os.getcwd() os.chdir(test_repo_path) try: site_config = load_site_config() return load_user_config(site_config) finally: os.chdir(original_dir)
def test_something(test_repo_path, test_config): """Test with fixture setup.""" original_dir = os.getcwd() os.chdir(test_repo_path) # Critical: change to test repo try: result = function_under_test() assert result == expected finally: os.chdir(original_dir) # Always restoreKey Testing Principles
Section titled “Key Testing Principles”- Repository context: Tests must
chdirto the fixture directory - Config isolation: Each test uses its own config via
MXCP_CONFIG - Complete fixtures: Include all necessary files (configs, endpoints, SQL)
- Cleanup: Always restore original directory using try/finally
- Independence: Tests should not depend on each other
Pull Request Process
Section titled “Pull Request Process”Before Submitting
Section titled “Before Submitting”- Follow code style guidelines (
./check-all.shpasses) - Run all tests and fix failures
- Update documentation if needed
- Rebase on main
Creating the PR
Section titled “Creating the PR”- Use the PR template
- Write clear title and description
- Link related issues
- Request review from maintainers
During Review
Section titled “During Review”- Address review comments promptly
- Keep PR up to date with main
- Squash commits if requested
After Approval
Section titled “After Approval”- Wait for CI to pass
- Address final comments
- Maintainers will merge
Architecture Patterns
Section titled “Architecture Patterns”This section covers internal patterns for contributors working on core MXCP code.
Configuration Loading
Section titled “Configuration Loading”# Standard pattern for CLI commandstry: site_config = load_site_config() user_config = load_user_config(site_config)
result = do_work()
except Exception as e: output_error(e, json_output, debug)Why this pattern?
- Site config defines project requirements
- User config provides personal settings and secrets
- Auto-generation allows projects to work out-of-the-box
- CLI layer owns configuration loading
DuckDB Connection Management
Section titled “DuckDB Connection Management”# Use DuckDBRuntime for connection poolingruntime = DuckDBRuntime(database_config, plugins, plugin_config, secrets)
with runtime.get_connection() as session: result = session.execute_query_to_dict(sql, params)
runtime.shutdown() # For graceful shutdownConnection details:
- CLI commands: Create their own
DuckDBRuntimeinstance - Server mode: Shared runtime with pool (default: 2 × CPU cores)
- Thread safety: Each request gets its own connection from pool
- Reload: Pool drains and refreshes without downtime
CLI Command Pattern
Section titled “CLI Command Pattern”@click.command(name="command_name")@click.option("--profile", help="Profile name")@click.option("--json-output", is_flag=True, help="JSON output")@click.option("--debug", is_flag=True, help="Debug info")@click.option("--readonly", is_flag=True, help="Read-only mode")@track_command_with_timing("command_name")def command_name(profile, json_output, debug, readonly): """Command description."""
# Environment variable fallback if not profile: profile = get_env_profile() if not readonly: readonly = get_env_flag("MXCP_READONLY")
configure_logging(debug)
try: site_config = load_site_config() user_config = load_user_config(site_config)
result = do_work() output_result(result, json_output, debug)
except Exception as e: output_error(e, json_output, debug)Key patterns:
- Environment variable support:
MXCP_PROFILE,MXCP_DEBUG,MXCP_READONLY - Consistent options:
--profile,--json-output,--debug,--readonly - Early logging setup before any operations
- Structured output via
output_result()andoutput_error()
JSON Output Format
Section titled “JSON Output Format”// Success{"status": "ok", "result": {}}
// Error{"status": "error", "error": "Message", "traceback": "..."}Error Handling
Section titled “Error Handling”from mxcp.server.interfaces.cli.utils import output_error, configure_logging
def cli_command(debug: bool, json_output: bool): configure_logging(debug) # Set up logging first
try: # Command logic pass except Exception as e: output_error(e, json_output, debug) raise click.Abort()Release Process
Section titled “Release Process”MXCP uses automated CD via GitHub Actions.
Version Format
Section titled “Version Format”MXCP follows PEP 440 for version numbers:
- Git tags: Include
vprefix (v1.0.0,v1.0.0rc1) - Python package (pyproject.toml): No
vprefix (1.0.0,1.0.0rc1)
| Type | Git Tag | pyproject.toml | User Install |
|---|---|---|---|
| Stable | v1.0.0 | 1.0.0 | pip install mxcp |
| RC | v1.0.0rc1 | 1.0.0rc1 | pip install --pre mxcp |
| Beta | v1.0.0b1 | 1.0.0b1 | pip install --pre mxcp |
| Alpha | v1.0.0a1 | 1.0.0a1 | pip install --pre mxcp |
Users must use --pre to install pre-release versions (or specify exact version: pip install mxcp==1.0.0rc1).
Creating a Release
Section titled “Creating a Release”Using the release script (recommended):
./release.sh 1.0.0 # Stable./release.sh 1.0.0rc1 # Pre-release
# Then pushgit push origin maingit push origin v1.0.0Manual release:
# 1. Update version in pyproject.toml# 2. Commitgit add pyproject.tomlgit commit -m "Release v1.0.0"git push
# 3. Create and push taggit tag v1.0.0git push origin v1.0.0What Happens Automatically
Section titled “What Happens Automatically”- Version validation (tag matches pyproject.toml)
- Package build and validation
- PyPI publication (trusted publishing)
- CDN propagation wait (up to 10 minutes)
- Docker image build and push to
ghcr.io/raw-labs/mxcp
Typical Release Workflow
Section titled “Typical Release Workflow”# Alpha testing./release.sh 1.0.0a1 && git push origin main v1.0.0a1
# Beta (feature complete)./release.sh 1.0.0b1 && git push origin main v1.0.0b1
# Release candidate (final testing)./release.sh 1.0.0rc1 && git push origin main v1.0.0rc1
# Found bug, fix and new RC./release.sh 1.0.0rc2 && git push origin main v1.0.0rc2
# Stable release./release.sh 1.0.0 && git push origin main v1.0.0For minor/patch releases, skip pre-releases and go straight to stable.
Verifying the Release
Section titled “Verifying the Release”# Monitor: https://github.com/raw-labs/mxcp/actions# Verify: https://pypi.org/project/mxcp/
# Test installationpip install --upgrade mxcp # Stablepip install --pre --upgrade mxcp # Pre-releasemxcp --versionCommunication
Section titled “Communication”- Issues: Bug reports and feature requests
- Discussions: General questions and ideas
- Email: hello@raw-labs.com
- Code Review: GitHub PR reviews
Getting Help
Section titled “Getting Help”- Check the documentation
- Search existing issues
- Join community discussions
- Email for private matters
Code of Conduct
Section titled “Code of Conduct”Follow our Code of Conduct. We maintain a welcoming and inclusive community.
License
Section titled “License”MXCP is released under the Business Source License 1.1. See LICENSE for details. This license allows for non-production use and will convert to MIT after four years from the first public release.
Thank you for contributing to MXCP!