Contributing
Setup
bash
git clone https://github.com/mcp-hangar/mcp-hangar.git
cd mcp-hangar
# Python core development
cd packages/core
pip install -e ".[dev]"
# Or use root Makefile
cd ../..
make setupMonorepo Structure
MCP Hangar is a monorepo with multiple packages:
mcp-hangar/
├── packages/
│ ├── core/ # Python package (PyPI: mcp-hangar)
│ │ ├── mcp_hangar/ # Main Python code
│ │ ├── tests/ # Python tests
│ │ └── pyproject.toml # Python package config
│ ├── operator/ # Kubernetes operator (Go)
│ │ ├── api/ # CRD definitions
│ │ ├── cmd/ # Main entrypoints
│ │ ├── internal/ # Controller logic
│ │ └── go.mod # Go module config
│ └── helm-charts/ # Helm charts
│ ├── mcp-hangar/ # Core Helm chart
│ └── mcp-hangar-operator/ # Operator Helm chart
├── docs/ # MkDocs documentation
├── examples/ # Quick starts & demos
├── monitoring/ # Grafana, Prometheus configs
└── Makefile # Root orchestrationPython Core Structure
packages/core/mcp_hangar/
├── domain/ # DDD domain layer
│ ├── model/ # Aggregates, entities
│ ├── services/ # Domain services
│ ├── events.py # Domain events
│ └── exceptions.py
├── application/ # Application layer
│ ├── commands/ # CQRS commands
│ ├── queries/ # CQRS queries
│ └── sagas/
├── infrastructure/ # Infrastructure adapters
├── server/ # MCP server module
│ ├── __init__.py # Main entry point
│ ├── config.py # Configuration loading
│ ├── state.py # Global state management
│ └── tools/ # MCP tool implementations
├── observability/ # Metrics, tracing, health
├── stdio_client.py # JSON-RPC client
└── gc.py # Background workersCode Style
bash
cd packages/core
ruff check mcp_hangar tests --fix
ruff format mcp_hangar tests
mypy mcp_hangarConventions
| Item | Style |
|---|---|
| Classes | PascalCase |
| Functions | snake_case |
| Constants | UPPER_SNAKE_CASE |
| Events | PascalCase + past tense (ProviderStarted) |
Type Hints
Required for all new code. Use Python 3.11+ built-in generics:
python
def invoke_tool(
self,
tool_name: str,
arguments: dict[str, Any],
timeout: float = 30.0,
) -> dict[str, Any]:
...Testing
bash
cd packages/core
pytest -v -m "not slow"
pytest --cov=mcp_hangar --cov-report=html
# Or from root
make testTarget: >80% coverage on new code.
Writing Tests
python
def test_tool_invocation():
# Arrange
provider = Provider(provider_id="test", mode="subprocess", command=[...])
# Act
result = provider.invoke_tool("add", {"a": 1, "b": 2})
# Assert
assert result["result"] == 3Pull Requests
Create feature branch
Make changes following style guidelines
Add tests
Run checks:
bashcd packages/core pytest -v -m "not slow" pre-commit run --all-filesUpdate docs if needed
PR Template
markdown
## Description
Brief description.
## Type
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
## Testing
- [ ] Unit tests added
- [ ] All tests passArchitecture Guidelines
Value Objects:
python
provider_id = ProviderId("my-provider") # ValidatedEvents:
python
provider.ensure_ready()
for event in provider.collect_events():
event_bus.publish(event)Exceptions:
python
# Basic usage
raise ProviderStartError(
provider_id="my-provider",
reason="Connection refused"
)
# With diagnostics (preferred)
raise ProviderStartError(
provider_id="my-provider",
reason="MCP initialization failed: process crashed",
stderr="ModuleNotFoundError: No module named 'requests'",
exit_code=1,
suggestion="Install missing Python dependencies."
)
# Get user-friendly message
try:
provider.ensure_ready()
except ProviderStartError as e:
print(e.get_user_message())Logging:
python
logger.info("provider_started: %s, mode=%s", provider_id, mode)Releasing
Release Process Overview
MCP Hangar uses automated CI/CD for releases. The process ensures quality through:
- Version Validation — Tag must match
pyproject.tomlversion - Full Test Suite — All tests across Python 3.11-3.14
- Security Scanning — Dependency audit and container scanning
- Artifact Publishing — PyPI package and Docker images
Creating a Release
Option 1: Automated (Recommended)
Use the GitHub Actions workflow:
- Go to Actions → Version Bump
- Click Run workflow
- Select bump type:
patch,minor, ormajor - Optionally select pre-release suffix (
alpha.1,beta.1,rc.1) - Run (or use dry run to preview)
The workflow will:
- Update version in
pyproject.toml - Update
CHANGELOG.mdwith release date - Create and push the version tag
- Trigger the release pipeline automatically
Option 2: Manual
bash
# 1. Update version in packages/core/pyproject.toml
cd packages/core
sed -i '' 's/version = ".*"/version = "1.2.0"/' pyproject.toml
# 2. Update CHANGELOG.md - move Unreleased items to new version section
# 3. Commit changes
git add pyproject.toml CHANGELOG.md
git commit -m "chore: bump version to 1.2.0"
# 4. Create annotated tag
git tag -a v1.2.0 -m "Release v1.2.0"
# 5. Push
git push origin main
git push origin v1.2.0Pre-release Versions
Pre-releases are automatically published to TestPyPI:
bash
# Tag patterns for pre-releases
v1.0.0-alpha.1 # Alpha release
v1.0.0-beta.1 # Beta release
v1.0.0-rc.1 # Release candidateInstall pre-release:
bash
pip install --index-url https://test.pypi.org/simple/ mcp-hangar==1.0.0rc1Release Checklist
Before releasing, ensure:
- [ ] All tests pass locally:
cd packages/core && pytest -v - [ ] Linting passes:
pre-commit run --all-files - [ ] CHANGELOG.md is updated with all notable changes
- [ ] Documentation is updated for new features
- [ ] Breaking changes are clearly documented
- [ ] Version follows Semantic Versioning
Versioning Guidelines
We follow Semantic Versioning (SemVer):
| Change Type | Version Bump | Example |
|---|---|---|
| Bug fixes, patches | PATCH | 1.0.0 → 1.0.1 |
| New features (backward-compatible) | MINOR | 1.0.1 → 1.1.0 |
| Breaking changes | MAJOR | 1.1.0 → 2.0.0 |
Release Artifacts
Each release produces:
| Artifact | Location | Tags |
|---|---|---|
| Python Package | PyPI | Version number |
| Docker Image | GHCR | latest, X.Y.Z, X.Y, X |
| GitHub Release | Repository Releases | Changelog, install instructions |
Hotfix Process
For urgent fixes on released versions:
bash
# 1. Create hotfix branch from tag
git checkout -b hotfix/1.0.1 v1.0.0
# 2. Apply fix, add tests
# 3. Update version and changelog
# 4. Tag and push
git tag -a v1.0.1 -m "Hotfix: description"
git push origin v1.0.1
# 5. Cherry-pick to main if applicable
git checkout main
git cherry-pick <commit-hash>License
MIT
Code of Conduct
Please read our Code of Conduct before contributing.
First Contribution?
Look for issues labeled good first issue.
Questions? Open a Discussion.