Production-grade hot-load registry for MCP providers
Project description
MCP Hangar
Production-grade MCP provider registry with lazy loading, health monitoring, and container support.
Features
- Lazy Loading — Providers start only when invoked, tools visible immediately
- Container Support — Docker/Podman with auto-detection
- Provider Groups — Load balancing with multiple strategies
- Health Monitoring — Circuit breaker pattern with automatic recovery
- Auto-Discovery — Detect providers from Docker labels, K8s annotations, filesystem
- Automatic Retry — Built-in retry with exponential backoff for transient failures
- Real-Time Progress — See operation progress while waiting (
registry_invoke_stream) - Rich Errors — Human-readable errors with recovery hints
Quick Start
uv pip install .
python -m mcp_hangar.server --config config.yaml
Claude Desktop
{
"mcpServers": {
"mcp-hangar": {
"command": "python",
"args": ["-m", "mcp_hangar.server", "--config", "/path/to/config.yaml"],
"cwd": "/path/to/mcp-hangar"
}
}
}
HTTP Mode (LM Studio)
python -m mcp_hangar.server --http
# Server at http://localhost:8000/mcp
Configuration
providers:
# Subprocess
math:
mode: subprocess
command: [python, -m, examples.provider_math.server]
idle_ttl_s: 180
tools:
- name: add
description: "Add two numbers"
inputSchema:
type: object
properties:
a: { type: number }
b: { type: number }
required: [a, b]
# Container
sqlite:
mode: container
image: localhost/mcp-sqlite:latest
volumes:
- "/absolute/path/to/data:/data:rw" # Must be absolute
network: bridge
idle_ttl_s: 300
Note: Use absolute paths for volume mounts. Relative paths fail when MCP clients start the server from different directories.
Building Container Images
podman build -t localhost/mcp-sqlite -f docker/Dockerfile.sqlite .
podman build -t localhost/mcp-memory -f docker/Dockerfile.memory .
podman build -t localhost/mcp-filesystem -f docker/Dockerfile.filesystem .
podman build -t localhost/mcp-fetch -f docker/Dockerfile.fetch .
mkdir -p data/sqlite data/memory data/filesystem
Registry Tools
| Tool | Description |
|---|---|
registry_list |
List providers |
registry_start |
Start provider |
registry_stop |
Stop provider |
registry_invoke |
Invoke tool |
registry_invoke_ex |
Invoke with retry & progress |
registry_invoke_stream |
Invoke with real-time progress ⭐ |
registry_tools |
Get tool schemas |
registry_details |
Provider details |
registry_health |
Health status |
registry_status |
Status dashboard |
registry_warm |
Pre-start providers |
Examples
# List providers (containers stay OFF)
registry_list()
# Get tools (container still OFF)
registry_tools(provider="sqlite")
# Invoke tool (starts container, executes)
registry_invoke(provider="sqlite", tool="execute",
arguments={"sql": "CREATE TABLE users (id INTEGER PRIMARY KEY)"})
registry_invoke(provider="sqlite", tool="query",
arguments={"sql": "SELECT * FROM users"})
# With automatic retry and correlation_id (recommended for production)
registry_invoke_ex(provider="sqlite", tool="query",
arguments={"sql": "SELECT * FROM users"},
max_retries=3,
correlation_id="my-trace-001")
# Returns: _retry_metadata with correlation_id, attempts, retries
# On error: includes final_error_reason and recovery_hints
# With real-time progress notifications (model sees progress!)
registry_invoke_stream(provider="sqlite", tool="query",
arguments={"sql": "SELECT * FROM large_table"},
correlation_id="stream-trace-001")
# Progress: [1/5] [cold_start] Provider is cold, launching...
# Progress: [2/5] [launching] Starting subprocess provider...
# Progress: [3/5] [ready] Provider ready
# Progress: [4/5] [executing] Calling tool 'query'...
# Progress: [5/5] [complete] Operation completed in 234ms
# Status dashboard
registry_status()
# ✅ math ready last: 2s ago
# ⏸️ sqlite cold Will start on request
# Pre-warm providers to avoid cold start latency
registry_warm("math,sqlite")
Provider Groups
providers:
math-cluster:
mode: group
strategy: weighted_round_robin
min_healthy: 2
members:
- id: math-1
weight: 3
mode: subprocess
command: [python, -m, examples.provider_math.server]
- id: math-2
weight: 1
mode: subprocess
command: [python, -m, examples.provider_math.server]
Strategies: round_robin, weighted_round_robin, random, priority, least_connections
Environment Variables
| Variable | Default | Description |
|---|---|---|
MCP_CONFIG |
config.yaml |
Config file path |
MCP_HTTP_PORT |
8000 |
HTTP server port |
MCP_RATE_LIMIT_RPS |
10 |
Rate limit |
MCP_CONTAINER_RUNTIME |
auto | Force podman or docker |
Development
git clone https://github.com/mapyr/mcp-hangar.git
cd mcp-hangar
uv sync --extra dev
uv run pytest tests/ -v -m "not slow"
Documentation
- Container Guide
- Discovery
- Observability - Metrics, tracing, health checks
- UX Improvements - Retry, progress, rich errors
- Architecture
- Testing
- Contributing
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_hangar-0.1.1.tar.gz.
File metadata
- Download URL: mcp_hangar-0.1.1.tar.gz
- Upload date:
- Size: 448.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac9ee8cb7fef375ee5d96b4d5a98d8dd01953e7fdedde8e9a35ca91eda5db9a3
|
|
| MD5 |
06be78f7c1b1684c7243667ea4299f08
|
|
| BLAKE2b-256 |
90d61adc8628575fd535f0d54f61865c28e35c319868efb89880114c0fb21dc6
|
Provenance
The following attestation bundles were made for mcp_hangar-0.1.1.tar.gz:
Publisher:
release.yml on mapyr/mcp-hangar
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_hangar-0.1.1.tar.gz -
Subject digest:
ac9ee8cb7fef375ee5d96b4d5a98d8dd01953e7fdedde8e9a35ca91eda5db9a3 - Sigstore transparency entry: 814915862
- Sigstore integration time:
-
Permalink:
mapyr/mcp-hangar@0c129861f4a5d7ef9b859b4572e6a0001c31df60 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mapyr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0c129861f4a5d7ef9b859b4572e6a0001c31df60 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file mcp_hangar-0.1.1-py3-none-any.whl.
File metadata
- Download URL: mcp_hangar-0.1.1-py3-none-any.whl
- Upload date:
- Size: 273.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10cb156a0e35e7a154b308d2049b28449603c1cd74403fc68ea7c721ac885bab
|
|
| MD5 |
ac54e408f7d44158d7c474a540f66906
|
|
| BLAKE2b-256 |
fc1acae7e2b924199f3f1fff75a8c231fbe77c7d652a2b0f447371985f73c388
|
Provenance
The following attestation bundles were made for mcp_hangar-0.1.1-py3-none-any.whl:
Publisher:
release.yml on mapyr/mcp-hangar
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_hangar-0.1.1-py3-none-any.whl -
Subject digest:
10cb156a0e35e7a154b308d2049b28449603c1cd74403fc68ea7c721ac885bab - Sigstore transparency entry: 814915867
- Sigstore integration time:
-
Permalink:
mapyr/mcp-hangar@0c129861f4a5d7ef9b859b4572e6a0001c31df60 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mapyr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0c129861f4a5d7ef9b859b4572e6a0001c31df60 -
Trigger Event:
workflow_dispatch
-
Statement type: