Skip to content

Protect an MCP Server

Use the MCP transport packages when your MCP framework does not have a dedicated Caracal connector or when you want to build your own boundary.

Terminal window
npm install @caracalai/transport-mcp @caracalai/revocation
import { createMandateVerifier } from "@caracalai/transport-mcp";
import { InMemoryRevocationStore } from "@caracalai/revocation";
const verifier = createMandateVerifier({
issuer: "https://sts.example.com",
audience: "https://mcp.example.com",
zoneId: "zone_prod",
revocations: new InMemoryRevocationStore(),
});
export async function verifyToolRequest(authorization: string | undefined) {
const result = await verifier.authorization(authorization, {
requiredScopes: ["mcp:tool:call"],
requiredTargets: ["https://mcp.example.com"],
requireAgent: true,
});
if (!result.ok) {
throw new Error(`${result.error.code}: ${result.error.description}`);
}
return result.principal;
}
Terminal window
pip install caracalai-transport-mcp caracalai-revocation
from caracalai_transport_mcp import authenticate, extract_bearer
from caracalai_revocation import InMemoryRevocationStore
revocations = InMemoryRevocationStore()
async def verify_tool_request(authorization: str | None):
token = extract_bearer(authorization)
result = await authenticate(
token or "",
issuer="https://sts.example.com",
audience="https://mcp.example.com",
required_scopes=["mcp:tool:call"],
expected_zone_id="zone_prod",
revocations=revocations,
require_agent=True,
required_targets=["https://mcp.example.com"],
)
if result.error is not None:
raise RuntimeError(f"{result.error.code}: {result.error.description}")
return result.principal
CheckWhy it matters
Issuer and audiencePrevents accepting mandates from the wrong zone or target.
Required scopesEnforces tool-level authority.
Required targetsPrevents cross-resource token reuse.
Agent or delegation requirementsKeeps user-root and delegated calls separate.
Revocation storeRejects revoked sessions and delegation edges.

Use Redis-backed revocation packages for multi-instance MCP servers:

  • TypeScript: @caracalai/revocation-redis
  • Python: caracalai-revocation-redis
  • Go: github.com/garudex-labs/caracal/packages/connectors/redis/go

Run a consumer for the caracal.sessions.revoke stream so every resource server instance learns about revoked anchors.

Related pages: Protect an Express App and Protect a FastMCP App.