---
title: "Protect a FastMCP App"
url: "https://docs.caracal.run/guides/protect-fastmcp/"
markdown_url: "https://docs.caracal.run/markdown/guides/protect-fastmcp.md"
description: "Attach CaracalAuth to a FastMCP server so tool calls are mandate-verified before handlers run."
page_type: "page"
concepts: []
requires: []
---

# Protect a FastMCP App

Canonical URL: https://docs.caracal.run/guides/protect-fastmcp/
Markdown URL: https://docs.caracal.run/markdown/guides/protect-fastmcp.md
Description: Attach CaracalAuth to a FastMCP server so tool calls are mandate-verified before handlers run.
Page type: page
Concepts: none
Requires: none

---

Use `caracalai-mcp-fastmcp` when a Python FastMCP app should reject invalid, expired, insufficient, or revoked Caracal mandates.

## Install

```bash
pip install "caracalai-mcp-fastmcp[fastmcp]" caracalai-revocation
```

Use `caracalai-revocation-redis` for shared production revocation. The in-memory store is only for local development and tests.

## Create an authenticator

```python
from caracalai_mcp_fastmcp import CaracalAuth
from caracalai_revocation import InMemoryRevocationStore

auth = CaracalAuth(
    issuer="https://sts.example.com",
    audience="https://mcp.example.com",
    expected_zone_id="zone_prod",
    required_scopes=["mcp:tool:call"],
    required_targets=["https://mcp.example.com"],
    revocations=InMemoryRevocationStore(),
    require_agent=True,
)

async def startup():
    await auth.warmup()
```

## Verify before running a tool

```python
from caracalai_mcp_fastmcp import CaracalAuthError

async def handle_tool_call(token: str, payload: dict):
    try:
        claims = await auth(token)
    except CaracalAuthError as err:
        return {"error": err.code, "error_description": err.description, "error_hint": err.hint}

    return {
        "subject": claims.sub,
        "result": await run_tool(payload),
    }
```

Wire this check into the FastMCP auth or request hook used by your server. The important boundary is that the mandate is verified before the tool handler performs work.

## Validate

| Test | Expected result |
| --- | --- |
| Missing bearer token | `missing_token` or framework 401. |
| Wrong audience | `invalid_token`. |
| Missing scope | `insufficient_scope`. |
| Revoked session | `session_revoked`. |
| Non-agent token with `require_agent=True` | `agent_required`. |

Related pages: [Protect an MCP Server](/guides/protect-mcp/) and [Step-Up Re-Authentication](/guides/step-up/).
