Development Guide¶
Guide for contributors and developers working on MCP BigQuery.
Development Setup¶
Prerequisites¶
- Python 3.10+
- Git
- Google Cloud SDK with BigQuery API enabled
Clone and Install¶
# Clone repository
git clone https://github.com/caron14/mcp-bigquery.git
cd mcp-bigquery
# Install with development dependencies
pip install -e ".[dev]"
# Or using uv
uv pip install -e ".[dev]"
Environment Setup¶
# Set up Google Cloud authentication
gcloud auth application-default login
# Configure project
export BQ_PROJECT="your-test-project"
export BQ_LOCATION="US"
# Install pre-commit hooks
pre-commit install
# Run development server
python -m mcp_bigquery
Pre-commit Setup¶
This project uses pre-commit hooks to ensure code quality:
# Install pre-commit hooks (one-time setup)
pre-commit install
# Run all hooks manually
pre-commit run --all-files
# Update hook versions
pre-commit autoupdate
Configured hooks: - isort: Sorts Python imports - black: Formats Python code (line length: 100) - flake8: Checks Python code style - ruff: Fast Python linter - mypy: Type checking for Python
Project Structure¶
mcp-bigquery/
├── src/mcp_bigquery/
│ ├── __init__.py # Package initialization
│ ├── __main__.py # Entry point
│ ├── server.py # MCP server implementation
│ └── bigquery_client.py # BigQuery client utilities
├── tests/
│ ├── test_min.py # Unit tests (no credentials)
│ ├── test_imports.py # Import validation
│ └── test_integration.py # Integration tests
├── docs/ # Documentation
├── examples/ # Usage examples
└── pyproject.toml # Project configuration
Testing¶
Run All Tests¶
# Run all tests
pytest tests/
# Run with coverage
pytest --cov=mcp_bigquery tests/
# Run specific test file
pytest tests/test_min.py -v
Test Categories¶
-
Unit Tests - No BigQuery credentials required
-
Integration Tests - Requires BigQuery access
Writing Tests¶
# Example unit test
import pytest
from mcp_bigquery.server import validate_sql
@pytest.mark.asyncio
async def test_validate_simple_query():
result = await validate_sql({"sql": "SELECT 1"})
assert result["isValid"] is True
# Example integration test
@pytest.mark.requires_credentials
async def test_public_dataset_query():
sql = "SELECT * FROM `bigquery-public-data.samples.shakespeare`"
result = await dry_run_sql({"sql": sql})
assert result["totalBytesProcessed"] > 0
Code Style¶
Formatting¶
# Format with black
black src/ tests/
# Check with ruff
ruff check src/ tests/
# Type checking with mypy
mypy src/
Style Guidelines¶
- Follow PEP 8
- Use type hints for all functions
- Add docstrings to public functions
- Keep functions small and focused
- Use descriptive variable names
Making Changes¶
1. Create Feature Branch¶
2. Make Changes¶
Follow the existing code patterns:
async def your_new_function(params: dict) -> dict:
"""
Brief description of function.
Args:
params: Dictionary with 'sql' and optional 'params'
Returns:
Dictionary with result or error
"""
try:
# Implementation
return {"success": True}
except Exception as e:
return {"error": {"code": "ERROR_CODE", "message": str(e)}}
3. Test Your Changes¶
4. Update Documentation¶
Update relevant documentation: - Add new features to README.md - Update API documentation - Add examples if applicable
5. Submit Pull Request¶
# Commit changes
git add .
git commit -m "feat: add new feature"
# Push to GitHub
git push origin feature/your-feature-name
Building and Publishing¶
Build Package¶
# Clean previous builds
rm -rf dist/ build/ *.egg-info
# Build distribution
python -m build
# Check package contents
tar -tzf dist/mcp-bigquery-*.tar.gz | head -20
Test Package Locally¶
# Install from local build
pip install dist/mcp-bigquery-*.whl
# Test installation
mcp-bigquery --version
Publish to PyPI¶
# Test on TestPyPI first
python -m twine upload --repository testpypi dist/*
# Publish to PyPI
python -m twine upload dist/*
Debugging¶
Enable Debug Logging¶
Common Issues¶
-
Import errors
-
Authentication errors
-
Test failures
Architecture Notes¶
MCP Server Implementation¶
The server follows MCP protocol standards:
- Tool Registration - Tools are registered in
handle_list_tools()
- Tool Execution - Requests handled in
handle_call_tool()
- Error Handling - Consistent error format across all tools
- Async Support - All operations are async for performance
BigQuery Client¶
- Uses Application Default Credentials (ADC)
- Respects environment variables (BQ_PROJECT, BQ_LOCATION)
- All queries run with
dry_run=True
- Cache disabled for accurate cost estimates
Error Handling¶
Standard error format:
{
"error": {
"code": "INVALID_SQL",
"message": "Human-readable error",
"location": {"line": 1, "column": 10},
"details": [] # Optional
}
}
Contributing Guidelines¶
- Open an issue first - Discuss major changes before implementing
- Follow existing patterns - Maintain consistency with current code
- Add tests - All new features need test coverage
- Update docs - Keep documentation in sync with code
- One feature per PR - Keep pull requests focused
Release Process¶
- Update version in
pyproject.toml
andsrc/mcp_bigquery/__init__.py
- Update CHANGELOG in README.md
- Create and push git tag
- Build and publish to PyPI
- Create GitHub release
Getting Help¶
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: This guide and API reference
License¶
MIT License - See LICENSE file for details