Progressive Deployment Playbook

This is the umbrella guide for taking MCP Hangar from a laptop to an internet-facing, authenticated gateway. It is a maturity model: each stage adds exactly one class of guarantee on top of the previous one, so you never turn on production controls before you have a working baseline to compare against.

Read this guide top to bottom to understand the progression and the decision points. Then follow the companion recipes for the copy-pasteable configs at each stage.

Audience

Operators who already have a single MCP server working behind Hangar (see Cookbook 01 -- HTTP Gateway) and now need to promote that setup through staging to production without guessing which knobs matter at which stage.

The Maturity Model

Hangar deployments move through four stages. Each row is a superset of the one above it -- you keep everything from the previous stage and add the new column.

StageTrust boundaryAuthTool surfaceDurability
Local devYour machine onlyOffFull hangar_* meta-APIIn-memory OK
StagingTrusted internal callersOn, internal keysFull hangar_* meta-APIDurable event store
Production read-onlyInternal, least-privilegeOn, RBACCurated, read-only toolsDurable + backups
External front doorUntrusted external agentsOIDC, per-tenantFlat per-tenant toolsDurable + backups

The single most important idea: the topology mode and the auth posture are the boundary, not the network. A staging box on a private subnet with auth off is not "internally safe" -- it is one misrouted route away from being open. Treat each stage's controls as the thing that holds the line.

What the Compose Examples Do Not Prove

Local Compose and self-signed profiles demonstrate wiring, not production security. Before you rely on any stage, be explicit that these are out of scope for the local examples and must come from your platform:

  • TLS termination with real certificates (Hangar expects a reverse proxy or load balancer in front -- nginx, Caddy, or Envoy).
  • A WAF or edge rate control for public exposure.
  • A real identity provider issuing signed JWTs. Hangar validates tokens; it does not mint them.
  • Secret management. Configs reference secrets by environment interpolation (${VAR}); they never store the literal value.

Stage 1: Local Development

The goal here is fast iteration, not safety. Run Hangar in the default topology mode with auth disabled so there is nothing between you and your tools.

# stdio for a desktop client, or HTTP to poke it with curl
mcp-hangar --config ./config.yaml serve --http --host 127.0.0.1 --port 8000

What is true at this stage:

  • Topology mode is the default egress: Hangar assumes trusted callers and exposes the full hangar_* meta-API.
  • Auth is off. Bind to 127.0.0.1 so nothing off-box can reach it.
  • The event store can run in memory -- volatile history is acceptable while you iterate.

The global --config also works after serve (both mcp-hangar --config X serve and mcp-hangar serve --config X are accepted), so you can standardize on one form across your scripts.

The companion recipe for this stage and the next is the local and staging profile cookbook (docs issue #18).

Stage 2: Staging

Staging is production's dress rehearsal. Same controls, non-production data. This is where you turn auth on and make durability real.

What changes from Stage 1:

  • Turn authentication on and stop allowing anonymous callers (auth.enabled: true, auth.allow_anonymous: false). Issue internal API keys per service principal. See Cookbook 12 -- Auth & RBAC.
  • Make the event store durable. Set event_store.driver: sqlite on a writable volume, and leave event_store.allow_memory_fallback: false so a non-writable path fails fast at startup instead of silently dropping the audit trail. When the fallback is taken, /health/ready reports 503.
  • Gate rollout on readiness. Point your orchestrator at /health/live (is the process up) and /health/ready (is it actually serving), and hold traffic until ready is green.
  • Enable discovery only if you rely on it, and pin its scope. Under discovery, list explicit sources (for example a docker source) rather than discovering everything on the host. See Cookbook 10 -- Discovery: Docker.

Emit structured logs from staging onward so your log pipeline sees the same shape it will see in production:

export MCP_JSON_LOGS=true
export MCP_LOG_LEVEL=INFO

Stage 3: Production Read-Only and Controlled-Write

Now the boundary tightens. Most tools should be observable and callable but not able to mutate host state; a small, audited set may write.

What changes from Stage 2:

  • Sandbox container-mode MCP servers. Run them read_only: true (the default for container specs) and grant persistence only through explicit writable volumes mounts, for example - "/absolute/path/to/data:/data:rw". Nothing outside a declared volume survives a restart, and nothing writes the root filesystem. See Cookbook 04 -- Failover and the Containers guide for the container-mode caveats.
  • Curate the tool surface with RBAC and per-target tool-access policy so each principal sees least-privilege. Controlled-write tools get their own role.
  • Put rate limiting in front of your backends. Configure rate_limit.rps / rate_limit.burst in config (these take precedence over the MCP_RATE_LIMIT_RPS / MCP_RATE_LIMIT_BURST env vars). See Cookbook 06 -- Rate Limiting.
  • Turn on tracing and metrics. OpenTelemetry tracing is on by default and is controlled by MCP_TRACING_ENABLED; scrape the Prometheus /metrics endpoint. See the Observability guide and Cookbook 07 -- Observability: Metrics.
  • Keep a rollback path: run behind a reverse proxy, pin images to a digest (not latest), and keep the previous config so a bad rollout is one revert away.

The companion recipe for this stage is the production read-only and controlled-write cookbook (docs issue #19).

Stage 4: External Multi-Tenant Front Door

The final stage flips the trust model. Hangar now faces untrusted external agents, so unauthenticated requests must be denied -- not proxied -- and each tenant sees only the tools you allow.

What changes from Stage 3:

  • Switch the topology mode: set tool_access.mode: front_door. In this mode a caller with no tenant identity is denied every tool (fail-closed), and external agents see flat per-tenant backend tool names instead of the hangar_* meta-API.
  • Front the gateway with a real OIDC issuer. Hangar validates the JWTs and maps a tenant claim onto the caller identity; per-tenant tool_access and tool projection then govern what each tenant can call. See the Front-Door guide and Cookbook 16 -- Front-Door Multi-Tenant.
  • Everything from Stage 3 still applies -- read-only sandboxes, RBAC, rate limits, tracing, durable event store, readiness gating -- plus the edge concerns (TLS, WAF, identity) listed under What the Compose Examples Do Not Prove.

The companion recipe for this stage is the external multi-tenant OIDC front-door cookbook (docs issue #20).

Try It

Verify the two guarantees that most often regress between stages: readiness gating and the fail-closed front door.

  1. Confirm the readiness contract while the process is live.

    curl -s -o /dev/null -w "live=%{http_code}\n" http://localhost:8000/health/live
    curl -s -o /dev/null -w "ready=%{http_code}\n" http://localhost:8000/health/ready

    Expected output once the server is serving:

    live=200
    ready=200

    If ready returns 503 while live is 200, the process is up but not serving -- for example a durable event store whose path is not writable. Hold traffic until ready is green.

  2. Confirm a front-door gateway denies an unauthenticated call.

    curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8000/mcp \
      -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}'

    Expected output when tool_access.mode: front_door and auth.allow_anonymous: false:

    401

What Just Happened

You did not deploy four different systems -- you deployed one system with four progressively stricter postures. Each stage changed a small, named set of controls:

  • Auth went from off (dev) to on (staging onward) to OIDC per-tenant (front door).
  • Topology went from the default egress (trusted callers, full meta-API) to front_door (untrusted agents, fail-closed, flat per-tenant tools).
  • Durability went from in-memory to a sqlite event store that fails fast rather than silently losing the audit trail.
  • Health gating used /health/live and /health/ready so rollouts wait for real readiness.
  • Guardrails -- read-only container sandboxes with explicit writable volumes, rate limits, tracing, and /metrics -- accumulated as you moved up.

Because the controls are named and additive, a promotion is a diff you can review, and a rollback is a diff you can revert.

Promotion Checklist

Walk this before each promotion. The full pre-launch list lives in Cookbook 13 -- Production Checklist.

  • Auth on for every stage above dev (auth.enabled: true, auth.allow_anonymous: false).
  • Per-principal API keys or OIDC issuer configured; RBAC roles are least-privilege.
  • Topology mode matches the trust boundary (egress internal, front_door external).
  • Event store durable (event_store.driver: sqlite) on a writable volume; allow_memory_fallback: false.
  • Container MCP servers run read_only: true; persistence only via explicit writable volumes.
  • Rate limiting set (rate_limit.rps / rate_limit.burst, or the MCP_RATE_LIMIT_RPS / MCP_RATE_LIMIT_BURST env vars).
  • Tracing and metrics wired (MCP_TRACING_ENABLED, Prometheus scraping /metrics).
  • Structured logging on (MCP_JSON_LOGS=true, MCP_LOG_LEVEL=INFO).
  • Orchestrator gates on /health/live and /health/ready.
  • Discovery scope pinned to explicit sources (no host-wide discovery).
  • Reverse proxy with real TLS in front; images pinned to a digest, not latest.
  • Rollback rehearsed: previous config and image kept, one revert away.

Companion Recipes

This umbrella guide references the following per-stage cookbooks. Where a dedicated recipe is still forthcoming, the nearest published guide is linked inline above.

  • Local and staging profile cookbook -- docs issue #18.
  • Production read-only and controlled-write cookbook -- docs issue #19.
  • External multi-tenant OIDC front-door cookbook -- docs issue #20.

Published references used at each stage today: