Upgrade Guide
This guide covers user-visible migration steps between MCP Hangar releases.
Upgrade to 1.5.0
MCP Hangar 1.5.0 adds a one-time admin bootstrap, a configurable command-bus
rate limit, the interceptor invocation surface with phase-aware hooks,
task-lifecycle audit events, and a per-tenant discovery entry point. It also
fixes OIDC bearer authentication over the HTTP surface. Upgrade is drop-in
(pip install -U mcp-hangar==1.5.0, or pull
ghcr.io/mcp-hangar/mcp-hangar:1.5.0); the notes below cover the behavior
changes worth reviewing.
OIDC bearer auth over serve --http now works
If you configured OIDC/JWT front-door auth (auth.oidc) on the HTTP server in
1.4.x and every request returned 401 with auth_method: none even for a valid
token, that was a header-casing bug in the JWT authenticator -- it is fixed in
1.5.0. No config change is needed; existing auth.oidc config now authenticates
bearer tokens as intended.
Bootstrap the initial admin
A fresh durable auth store with anonymous access disabled could not create its
first administrator through the protected API. mcp-hangar auth bootstrap-admin --config PATH --principal PRINCIPAL now grants the one-time global admin role
to an existing external (OIDC) principal using the server's own durable backend.
It fails closed when auth is disabled, anonymous access is allowed, or the store
is non-durable (memory / event_sourcing), and a second run is refused without
mutating storage. No secret is printed.
Behavior changes to review
- Tool
isErrorresults now count as failures. A backend MCP tool result withisError: trueis treated as a tool failure -- reflected in the per-call result, batchsucceeded/failedcounts, health, andToolInvocationFailedevents. If you previously treated error results as successes, expect failure counts to rise. - The SQLite event store fails fast. When a durable event store cannot be
initialized (path not writable / backend unavailable), Hangar now refuses to
start instead of silently degrading to a non-durable in-memory store. Opt into
the fallback with
event_store.driver: memoryorevent_store.allow_memory_fallback: true./health/readyreturns 503 if the store degraded to in-memory while a durable driver was configured. - Group circuit breaker. A tripped circuit breaker on one group member no longer blocks a healthy remaining member from serving.
- Command-bus rate limit is configurable. The previously-fixed command-bus
rate limit can now be tuned in
config.yaml; review the configuration reference if you relied on the old fixed value.
Upgrade to 1.4.0
MCP Hangar 1.4.0 builds on the 1.3 front-door release. It adds tenant-scoped digest pins, multi-issuer OIDC trust, resource-bound JWT audiences, and per-tenant canary routing for MCP server groups.
Review OIDC audience binding
If auth.oidc.resource_uri is set, it now becomes the expected JWT aud value
for every trusted issuer. This aligns token validation with the RFC 9728
Protected Resource Metadata resource value and RFC 8707 resource indicators.
Before upgrading production front-door deployments:
- Confirm the authorization server issues tokens with
audequal toauth.oidc.resource_uri. - If you need legacy audience values per issuer, leave
resource_uriunset and configureaudienceon each issuer instead. - Prefer setting
resource_uribehind proxies; otherwise Hangar derives the resource from the incoming request scheme and host.
Move multi-issuer deployments to auth.oidc.issuers
Single-issuer config still works:
auth:
oidc:
enabled: true
issuer: https://issuer-a.example.com
audience: mcp-hangar
Use auth.oidc.issuers when one Hangar instance trusts multiple authorization
servers:
auth:
oidc:
enabled: true
resource_uri: https://hangar.example.com
tenant_claim: tenant_id
issuers:
- issuer: https://issuer-a.example.com
audience: https://hangar.example.com
jwks_uri: https://issuer-a.example.com/jwks
- issuer: https://issuer-b.example.com
audience: https://hangar.example.com
jwks_uri: https://issuer-b.example.com/jwks
groups_claim: roles
Tokens with a missing, empty, non-string, or untrusted iss claim now fail
closed with a 401 instead of reaching any issuer validator.
Add tenant-scoped digest pins intentionally
1.4.0 can enforce schema pins per tenant on the live invocation path:
mcp_servers:
payments:
mode: remote
endpoint: https://payments.example.com/mcp
tool_projection:
digest_enforcement: block
tenant_overrides:
"tenant:a":
pins:
refund: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
digest_enforcement is scoped per MCP server. If unset, pin mismatches default
to block. Roll out pins with audit or warn first when you are recomputing
digests or onboarding a new tenant.
The deprecated allow_degraded unknown-tool policy is still accepted with a
DeprecationWarning in 1.4.0, but allow_unverified remains the canonical value.
Do not add new allow_degraded config.
Gate canary routing by tenant identity
Group canary routing only applies when Hangar has a tenant_id for the caller.
Explicit tenant pins win first, then the sticky percentage split, then the
regular load-balancing strategy.
mcp_servers:
search:
mode: group
strategy: weighted_round_robin
canary:
member: search-v2
split_pct: 10
pinned_tenants:
"tenant:beta": search-v2
members:
- id: search-v1
mode: remote
endpoint: https://search-v1.example.com/mcp
- id: search-v2
mode: remote
endpoint: https://search-v2.example.com/mcp
Invalid canary targets are skipped with a warning. If a pinned or canary member is not in rotation, Hangar falls back to the group load balancer instead of routing traffic to an unhealthy member.
Upgrade to 1.3.0
MCP Hangar 1.3.0 relicenses the project to MIT, folds the former enterprise
package into the main mcp_hangar package, and tightens digest-pinning
canonicalization.
Recompute pinned tool digests
compute_tool_digest() now uses RFC 8785 JSON Canonicalization Scheme (JCS)
instead of json.dumps output. Existing pinned digests produced by earlier
versions may no longer match and must be regenerated before enforcement mode is
enabled.
When recomputing digests, note the v1.3 normalization rules:
None,{},[], and""are treated as absent values.- Tool entries with a missing, empty, or non-string
namefield are rejected.
Recommended rollout:
- Upgrade one environment with digest enforcement set to
auditorwarn. - Collect the new expected digests from the audited tool inventory.
- Replace old pins with the RFC 8785/JCS digests.
- Re-enable
blockonly after the audited drift is resolved.
Rename ALLOW_DEGRADED to ALLOW_UNVERIFIED
DigestUnknownPolicy.ALLOW_DEGRADED was renamed to
DigestUnknownPolicy.ALLOW_UNVERIFIED for clarity.
If your YAML or code uses the string value allow_degraded, change it to
allow_unverified. MCP Hangar 1.3 still accepts allow_degraded with a
DeprecationWarning; 1.4.0 still accepts the alias, but new configuration should
use only allow_unverified.
Remove license-tier assumptions
The former BSL/enterprise split is gone. All MCP Hangar features are now available under the MIT license.
Required cleanup for integrations and deployment manifests:
- Stop setting
HANGAR_LICENSE_KEY; v1.3 ignores it and emits aDeprecationWarningwhen present. - Remove checks for
LicenseTier,LicenseValidation, orApplicationContext.license_tier. - Update imports that referenced the former
enterprise/package; auth, compliance, approvals, integrations, and persistence modules now live undersrc/mcp_hangar/.
Verify interceptor discovery clients
interceptors/list now returns unique instance names required by SEP-1763:
mcp-hangar-validatormcp-hangar-mutator
If a client keyed both entries by the previous shared name mcp-hangar, update
it to handle the two explicit instance names.