Contributing¶
Setup¶
git clone https://github.com/mcp-hangar/mcp-hangar.git
cd mcp-hangar
# Install with dev dependencies
pip install -e ".[dev]"
# Or use root Makefile
make setup
Monorepo Structure¶
MCP Hangar is a monorepo:
mcp-hangar/
├── src/mcp_hangar/ # Python package (PyPI: mcp-hangar) -- MIT
│ ├── auth/ # RBAC, API key, JWT/OIDC
│ ├── behavioral/ # Network profiling, deviation detection
│ ├── identity/ # Caller identity propagation, audit
│ ├── compliance/ # SIEM export (CEF, LEEF, JSON-lines)
│ ├── persistence/ # SQLite/Postgres event stores
│ ├── semantic/ # Pattern engine, detection rules
│ └── integrations/ # Langfuse adapter
├── tests/ # Python tests
├── packages/
│ ├── operator/ # Kubernetes operator (Go)
│ │ ├── api/ # CRD definitions
│ │ ├── cmd/ # Main entrypoints
│ │ ├── internal/ # Controller logic
│ │ └── go.mod # Go module config
│ ├── ui/ # React dashboard
│ └── helm-charts/ # Helm charts
│ ├── mcp-hangar/ # Core Helm chart
│ └── mcp-hangar-operator/ # Operator Helm chart
├── docs/ # MkDocs documentation
├── examples/ # Quick starts, OTEL recipes
├── monitoring/ # Grafana, Prometheus configs
└── Makefile # Root orchestration
Python Core Structure¶
src/mcp_hangar/
├── domain/ # DDD domain layer
│ ├── model/ # Aggregates, entities
│ ├── services/ # Domain services
│ ├── events.py # Domain events
│ ├── contracts/ # Interfaces consumed by src/mcp_hangar/
│ └── exceptions.py
├── application/ # Application layer
│ ├── commands/ # CQRS commands
│ ├── queries/ # CQRS queries
│ ├── ports/ # Port interfaces consumed by src/mcp_hangar/
│ └── sagas/
├── infrastructure/ # Infrastructure adapters
│ └── observability/ # OTLPAuditExporter
├── observability/ # Conventions, tracing, metrics, health
├── server/ # MCP server module
│ ├── bootstrap/ # DI composition root
│ ├── config.py # Configuration loading
│ ├── state.py # Global state management
│ └── tools/ # MCP tool implementations
├── stdio_client.py # JSON-RPC client
└── gc.py # Background workers
Licensing¶
- All code -- MIT. See LICENSE.
- Core and former enterprise code live in
src/mcp_hangar/; imports stay within package boundaries.
Code Style¶
Conventions¶
| Item | Style |
|---|---|
| Classes | PascalCase |
| Functions | snake_case |
| Constants | UPPER_SNAKE_CASE |
| Events | PascalCase + past tense (McpServerStarted) |
Type Hints¶
Required for all new code. Use Python 3.11+ built-in generics:
def invoke_tool(
self,
tool_name: str,
arguments: dict[str, Any],
timeout: float = 30.0,
) -> dict[str, Any]:
...
Testing¶
Target: >80% coverage on new code.
Writing Tests¶
def test_tool_invocation():
# Arrange
mcp_server = McpServer(mcp_server_id="test", mode="subprocess", command=[...])
# Act
result = mcp_server.invoke_tool("add", {"a": 1, "b": 2})
# Assert
assert result["result"] == 3
Pull Requests¶
See Git Flow for branching conventions, merge strategy, and commit scopes.
- Create feature branch
- Make changes following style guidelines
- Add tests
- Run checks:
- Update docs if needed
PR Template¶
PRs must follow the template in .github/PULL_REQUEST_TEMPLATE.md. Required sections are enforced by the pr-body / validate CI check.
Architecture Guidelines¶
Value Objects:
Events:
Exceptions:
# Basic usage
raise McpServerStartError(
mcp_server_id="my-mcp-server",
reason="Connection refused"
)
# With diagnostics (preferred)
raise McpServerStartError(
mcp_server_id="my-mcp-server",
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:
mcp_server.ensure_ready()
except McpServerStartError as e:
print(e.get_user_message())
Logging:
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¶
Releases are automated via release-please. When Conventional Commit PRs merge to main, release-please maintains a long-running Release PR that bumps the version and updates the changelog. Merging that PR creates the version tag, which release.yml consumes to publish to PyPI and GHCR.
See RELEASE.md for the full operational runbook.
Pre-release Versions¶
Pre-releases are automatically published to TestPyPI:
# 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 candidate
Install pre-release:
Release Checklist¶
Before releasing, ensure:
- [ ] All tests pass locally:
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, follow the HOTFIX_RUNBOOK.md.
Licensing Model¶
MCP Hangar is licensed under the MIT License:
| Directory | License |
|---|---|
src/mcp_hangar/ | MIT |
tests/, docs/, examples/, monitoring/ | 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.