Skip to main content
New in version 3.1.0 This guide shows you how to secure your FastMCP server using PropelAuth, a complete authentication and user management solution. This integration uses the 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 account
  2. Your FastMCP server’s base URL (can be localhost for development, e.g., http://localhost:8000)

Step 1: Configure PropelAuth

1

Enable MCP Authentication

Navigate to the MCP section in your PropelAuth dashboard, click Enable MCP, and choose which environments to enable it for (Test, Staging, Prod).
2

Configure Allowed MCP Clients

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.
3

Configure Scopes

Under MCP > Scopes, define the permissions available to MCP clients (e.g., read:user_data).
4

Choose How Users Create OAuth Clients

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.
5

Generate Introspection Credentials

Go to MCP > Request Validation and click Create Credentials. Note the Client ID and Client Secret - you’ll need these to validate tokens.
6

Note Your Auth URL

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.

Step 2: Environment Setup

Create a .env file with your PropelAuth configuration:
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:
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:
fastmcp run server.py --transport http --port 8000
Then use a FastMCP client to verify authentication works:
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:
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:
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)