Skip to content

ASGI Connector

The ASGI connector protects any Python ASGI application — FastAPI, Starlette, Quart, Django ASGI — with fail-closed Caracal mandate verification. It is pure ASGI: it imports no web framework and delegates every check to MCP Auth Transport.

Terminal window
pip install caracalai-asgi
from caracalai_asgi import CaracalASGIAuth
from caracalai_revocation import InMemoryRevocationStore
from fastapi import FastAPI
app = FastAPI()
app.add_middleware(
CaracalASGIAuth,
audience="resource://billing-api",
revocations=InMemoryRevocationStore(),
required_scopes=["billing:read"],
routes={
"/payouts": {"required_scopes": ["billing:payout"], "require_delegation": True},
},
exclude=["/healthz"],
)
@app.get("/balances")
async def balances(request):
principal = request.state.caracal
return {"sub": principal.sub, "scopes": principal.scope}

issuer defaults to CARACAL_STS_URL and expected_zone_id to CARACAL_ZONE_ID, so a provider deployed with the standard Caracal workload variables only states its own audience and revocation store. Construction fails if no issuer can be resolved.

OptionUse it for
audienceThe provider’s own resource identifier; mandates minted for other resources are rejected.
revocationsRevocation store consulted on every request. Use Redis Revocation Store in production.
required_scopes / required_targetsDefault scope and target requirements for every route.
require_agent / require_delegation / max_hop_countAgent identity, delegated authority, and delegation-depth requirements.
routesPer-route overrides by path prefix; the longest matching prefix wins. Any option above can be overridden.
excludePath prefixes served without verification (health and readiness probes).
  • Verified claims are stored as scope["state"]["caracal"], surfaced as request.state.caracal in Starlette and FastAPI.
  • Failed verification answers with the shared status mapping (http_status_for_auth_error): 401 for credential failures, 403 for insufficient authority, with the standard error/error_description JSON body.
  • WebSocket connections that fail verification are closed with policy code 1008; lifespan events pass through.
  • Call await middleware.warmup() at startup to prefetch the zone JWKS before the first request.

The connector verifies inbound mandates; it does not create agent sessions or delegation edges. Use the Python SDK to create Caracal context before making outbound calls.