--- title: PropelAuth 🤝 FastMCP sidebarTitle: PropelAuth description: Secure your FastMCP server with PropelAuth icon: shield-check --- import { VersionBadge } from "/snippets/version-badge.mdx"; This guide shows you how to secure your FastMCP server using [**PropelAuth**](https://www.propelauth.com), a complete authentication and user management solution. This integration uses the [**Remote OAuth**](/servers/auth/remote-oauth) pattern, where PropelAuth handles user login, consent management, and your FastMCP server validates the tokens. ## Configuration ### Prerequisites Before you begin, you will need: 1. A [PropelAuth](https://www.propelauth.com) account 2. Your FastMCP server's base URL (can be localhost for development, e.g., `http://localhost:8000`) ### Step 1: Configure PropelAuth Navigate to the **MCP** section in your PropelAuth dashboard, click **Enable MCP**, and choose which environments to enable it for (Test, Staging, Prod). Under **MCP > Allowed MCP Clients**, add redirect URIs for each MCP client you want to allow. PropelAuth provides templates for popular clients like Claude, Cursor, and ChatGPT. Under **MCP > Scopes**, define the permissions available to MCP clients (e.g., `read:user_data`). Under **MCP > Settings > How Do Users Create OAuth Clients?**, you can optionally enable: - **Dynamic Client Registration** — clients self-register automatically via the DCR protocol - **Manually via Hosted Pages** — PropelAuth creates a UI for your users to register OAuth clients You can enable neither, one, or both. If you enable neither, you'll manage OAuth client creation yourself. Go to **MCP > Request Validation** and click **Create Credentials**. Note the **Client ID** and **Client Secret** - you'll need these to validate tokens. Find your Auth URL in the **Backend Integration** section of the dashboard (e.g., `https://auth.yourdomain.com`). For more details, see the [PropelAuth MCP documentation](https://docs.propelauth.com/mcp-authentication/overview). ### Step 2: Environment Setup Create a `.env` file with your PropelAuth configuration: ```bash PROPELAUTH_AUTH_URL=https://auth.yourdomain.com # From Backend Integration page PROPELAUTH_INTROSPECTION_CLIENT_ID=your-client-id # From MCP > Request Validation PROPELAUTH_INTROSPECTION_CLIENT_SECRET=your-client-secret # From MCP > Request Validation SERVER_URL=http://localhost:8000 # Your server's base URL ``` ### Step 3: FastMCP Configuration Create your FastMCP server file and use the PropelAuthProvider to handle all the OAuth integration automatically: ```python server.py import os from fastmcp import FastMCP from fastmcp.server.auth.providers.propelauth import PropelAuthProvider auth_provider = PropelAuthProvider( auth_url=os.environ["PROPELAUTH_AUTH_URL"], introspection_client_id=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_ID"], introspection_client_secret=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_SECRET"], base_url=os.environ["SERVER_URL"], required_scopes=["read:user_data"], # Optional scope enforcement ) mcp = FastMCP(name="My PropelAuth Protected Server", auth=auth_provider) ``` ## Testing With your `.env` loaded, start the server: ```bash fastmcp run server.py --transport http --port 8000 ``` Then use a FastMCP client to verify authentication works: ```python from fastmcp import Client import asyncio async def main(): async with Client("http://localhost:8000/mcp", auth="oauth") as client: assert await client.ping() if __name__ == "__main__": asyncio.run(main()) ``` ## Accessing User Information You can use `get_access_token()` inside your tools to identify the authenticated user: ```python server.py import os from fastmcp import FastMCP from fastmcp.server.auth.providers.propelauth import PropelAuthProvider from fastmcp.server.dependencies import get_access_token auth = PropelAuthProvider( auth_url=os.environ["PROPELAUTH_AUTH_URL"], introspection_client_id=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_ID"], introspection_client_secret=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_SECRET"], base_url=os.environ["SERVER_URL"], required_scopes=["read:user_data"], ) mcp = FastMCP(name="My PropelAuth Protected Server", auth=auth) @mcp.tool def whoami() -> dict: """Return the authenticated user's ID.""" token = get_access_token() if token is None: return {"error": "Not authenticated"} user_id = token.claims.get("sub") return {"user_id": user_id} ``` ## Advanced Configuration The `PropelAuthProvider` supports optional overrides for token introspection behavior, including caching and request timeouts: ```python server.py import os from fastmcp import FastMCP from fastmcp.server.auth.providers.propelauth import PropelAuthProvider auth = PropelAuthProvider( auth_url=os.environ["PROPELAUTH_AUTH_URL"], introspection_client_id=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_ID"], introspection_client_secret=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_SECRET"], base_url=os.environ.get("BASE_URL", "https://your-server.com"), required_scopes=["read:user_data"], resource="https://your-server.com/mcp", # Restrict to tokens intended for this server (RFC 8707) token_introspection_overrides={ "cache_ttl_seconds": 300, # Cache introspection results for 5 minutes "max_cache_size": 1000, # Maximum cached tokens "timeout_seconds": 15, # HTTP request timeout }, ) mcp = FastMCP(name="My PropelAuth Protected Server", auth=auth) ```