Skip to main content
TrueFoundry AI Gateway provides a comprehensive authentication and authorization system that separates how users authenticate to the Gateway from how the Gateway authenticates to downstream MCP servers. This separation lets administrators choose the right security posture per tool without forcing end users to manage multiple credentials.

Authentication Architecture Overview

The Gateway provides a four-layer authentication and authorization system:
LayerDescription
Gateway AuthenticationUsers authenticate to the Gateway using TrueFoundry tokens, Virtual Accounts, or your IdP tokens
Access ControlRole-based policies determine which users can access which MCP servers
MCP Server AuthenticationHow the Gateway authenticates to downstream MCP servers (per-user, shared, or passthrough)
Custom HeadersPass additional headers to MCP servers for specialized use cases
MCP Gateway Authentication and Authorization Flow

MCP Gateway Authentication and Authorization Flow


Layer 1: Gateway Authentication

Any user or application requires a token to talk to the Gateway. This allows the Gateway to identify the caller and apply authorization rules. TrueFoundry supports three authentication methods:
For internal developers and applications with TrueFoundry accounts. Users generate a Personal Access Token (PAT) from the TrueFoundry UI.
1

Generate a Personal Access Token

  1. Navigate to Settings > API Keys in the TrueFoundry UI
  2. Click Generate New API Key
  3. Store the token securely
2

Use the token in requests

from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

transport = StreamableHttpTransport(
    url="https://<control-plane-url>/api/llm/mcp/<integration-id>/server",
    headers={"Authorization": "Bearer <your-tfy-api-key>"}
)

async with Client(transport) as client:
    result = await client.call_tool("tool_name", {"arg": "value"})
Virtual Accounts are service accounts with specific permissions to access MCP servers. Use Virtual Accounts when you need a shared token for server-to-server communication or when building applications where individual user identity isn’t required at the Gateway level.
1

Create a Virtual Account

  1. Navigate to Settings > Virtual Accounts in the TrueFoundry UI
  2. Click Create Virtual Account
  3. Give it a descriptive name (e.g., my-agent-mcp-access)
  4. Add permissions for the MCP servers your application needs to access
2

Generate and use the token

from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

# Virtual Account token - same for all requests from your application
VA_TOKEN = "your-virtual-account-token"

transport = StreamableHttpTransport(
    url="https://<control-plane-url>/api/llm/mcp/<integration-id>/server",
    headers={"Authorization": f"Bearer {VA_TOKEN}"}
)

async with Client(transport) as client:
    result = await client.call_tool("tool_name", {"arg": "value"})
Virtual Account tokens provide the same level of access for all requests. For MCP servers that require user-specific access (like accessing a user’s GitHub repositories), use OAuth2 with individual user tokens instead.
For end customers or when you want to use your own identity provider (Okta, Azure AD, Auth0, Cognito, etc.). The AI Gateway validates your IdP token and extracts the user’s identity based on your SSO settings.This approach is ideal for:
  • B2B SaaS applications where your customers don’t have TrueFoundry accounts
  • Applications that want to use their existing identity infrastructure
  • Customer Identity and Access Management (CIAM) scenarios
1

Configure SSO Integration

Register your IdP with TrueFoundry:
  1. Navigate to Settings > SSO
  2. Create a new SSO configuration pointing to your IdP
  3. Important: Set login enabled to false (this SSO is only for external identity, not platform login)
  4. Note the SSO FQN for the next step
2

Create External Identity

Create an External Identity that maps JWTs from your IdP to TrueFoundry access:
  1. Navigate to Access > External Identities
  2. Click Add External Identity
  3. Select the SSO FQN from step 1
  4. Optionally add claims to match specific users/tenants
For detailed instructions, see Setup External Identity.
3

Grant MCP server access

Add the External Identity as a collaborator on the MCP server:
  1. Navigate to the MCP server’s settings
  2. Go to Collaborators
  3. Add the External Identity with appropriate permissions
4

Use your IdP token in requests

When your end user logs into your platform, your application receives their JWT. Use that JWT to authenticate with the Gateway:
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

# JWT from your IdP (e.g., Auth0, Okta)
user_jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

transport = StreamableHttpTransport(
    url="https://<control-plane-url>/api/llm/mcp/<integration-id>/server",
    headers={"Authorization": f"Bearer {user_jwt}"}
)

async with Client(transport) as client:
    result = await client.call_tool("tool_name", {"arg": "value"})

Layer 2: Access Control at the Gateway

You can define which users have access to which MCP servers at the Gateway layer. MCP Server Group Access Control Access control is enforced based on:
  • User identity (TrueFoundry user, Virtual Account, or External Identity)
  • Role-based permissions assigned to users or groups
  • MCP server group membership
You can also create a Virtual MCP Server to expose a subset of tools from different MCP servers and grant access to specific users or teams.

Layer 3: MCP Server Authentication Models

This layer handles how the Gateway authenticates to downstream MCP servers. TrueFoundry supports four authentication models, each suited for different use cases.
The MCP server doesn’t require any authentication. Suitable for:
  • Demo or sandbox APIs
  • Public tools like a Calculator MCP Server or DeepWiki MCP server
Not recommended for production MCP servers or any server that provides access to sensitive data.
The MCP server requires a static API key or token that is the same for all requests. You configure this credential once, and the Gateway injects it into every request regardless of which end user is calling.When to use shared service accounts:
  • Datasets meant for broad team or department access
  • Read-only access to shared resources (knowledge bases, analytics)
  • Legacy systems without per-user OAuth support
  • Internal tools where a service account is easier to audit
Example: A Hugging Face MCP server uses a shared API token. Users connect through the Gateway with their TrueFoundry credentials, while the Gateway injects the shared token and enforces which models or datasets each role can access.
The MCP server requires end-user-specific OAuth tokens to access external services like GitHub, Slack, or Atlassian. Each end user must complete an OAuth consent flow to grant access to their resources on those services.When to use per-user OAuth:
  • Personal productivity tools (email, calendar, documents)
  • Systems where permissions differ per user
  • Actions that must be attributed to an individual
  • Compliance requirements that need end-to-end user traceability
How OAuth2 works:
  1. End user authenticates with the Gateway (using TrueFoundry token or External Identity)
  2. End user attempts to call an MCP tool → Gateway returns auth error with authorization URL
  3. End user visits URL and completes OAuth consent on the third-party service (e.g., GitHub)
  4. TrueFoundry stores the OAuth token for that end user
  5. Future requests automatically include the end user’s OAuth token
Example: A Slack MCP server prompts each employee to authorize their account during first use. TrueFoundry stores the OAuth refresh token, rotates it automatically, and injects it only when that user invokes a Slack tool. Each user can only access their own messages and channels.
Key point: With OAuth2, end users authenticate twice - once with the Gateway, and once with the third-party service (GitHub, Slack, etc.) to grant access to their resources there.
The MCP server expects to receive a JWT that you issue to your end users. TrueFoundry passes this JWT directly to the MCP server without any transformation.When to use Token Passthrough:
  • You have your own IdP (e.g., Auth0, Okta, Cognito) that authenticates your end users
  • The MCP server is configured to validate JWTs from your IdP
  • You want to control authentication entirely through your own system
How Token Passthrough works:
  1. Your end user authenticates with your IdP and receives a JWT
  2. End user calls your agent with their JWT
  3. TrueFoundry passes the JWT directly to the MCP server
  4. The MCP server validates the JWT against your IdP’s configuration
Key point: This is for when the MCP server trusts your IdP. Your end users authenticate with you, and that authentication is passed through directly.

Mixing Authentication Strategies

Organizations commonly mix multiple approaches within the same deployment:
MCP ServerAuth StrategyReason
Gmail, SlackPer-user OAuthPersonal data, user-specific permissions
Internal Database MCPShared service accountRead-only analytics access
GitHubPer-user OAuthUser-specific repo access and commit attribution
Custom Internal APIToken PassthroughUses organization’s IdP for validation
The Gateway keeps the user-facing experience consistent even when different MCP servers use different authentication models.

Configuring MCP Server Authentication

When registering an MCP server, choose the authentication type that determines how requests are authenticated with the upstream MCP server.
The MCP server can be accessed without authentication. This is suitable for:
  • Demo or sandbox APIs
  • Public tools like a Calculator MCP Server or DeepWiki MCP server
DeepWiki MCP server configuration with No Auth option selected
Not recommended for production MCP servers or any server that provides access to sensitive data.
Configure specific headers that the Gateway passes to the MCP Server. All users share the same downstream credentials.Example: Hugging Face MCP ServerDefine the Hugging Face Token as the Authorization header value. Users authenticate to the Gateway with their TrueFoundry or IdP token, and the Gateway forwards requests with the shared Hugging Face token after RBAC checks pass.Hugging Face MCP server configuration with Header Auth option selected
Use static header auth for MCP servers that don’t support user-specific OAuth and rely on API keys or tokens. All users calling this MCP server will use the same downstream credentials.
Each user authenticates individually, and the MCP server grants access only to resources that user is authorized to use. OAuth2 is supported by popular services like Slack, GitHub, Atlassian, Google, and more.
Recommended for production. OAuth2 allows you to configure scopes (e.g., read-only), users can revoke their own authorization, and access is limited to resources each user is permitted to use.
1

Create an OAuth2 app in your provider's developer portal

Set the redirect URI to:
https://<tfy-control-plane-base-url>/api/svc/v1/llm-gateway/mcp-servers/oauth2/callback
Replace <tfy-control-plane-base-url> with your TrueFoundry control plane URL. Note your OAuth2 App ID, Secret, and required scopes.
2

Register the MCP Server in the AI Gateway

  1. Navigate to MCP Servers tab and click Add New MCP Server Group MCP Server registration interface in AI Gateway
  2. Click Add MCP Server and provide:
    • Endpoint URL: The URL of your MCP Server
    • Authentication Type: Select OAuth2
    • OAuth2 App ID: The client ID from your OAuth2 app
    • OAuth2 App Secret: The client secret
    • OAuth2 App Scopes: Required scopes for accessing resources
    AI Gateway form for adding a new MCP Server with OAuth2 authentication
Store OAuth2 credentials in the TrueFoundry secrets store and reference their FQN for enhanced security.
3

Connect and authorize

  1. Click Add Tool/MCP Servers in the AI Gateway UI
  2. For OAuth2 MCP Servers, click Connect Now to authorize
OAuth2 authorization interface for MCP Server in AI Gateway

Authorize your MCP Server in AI Gateway

  1. Once authorized, the MCP Server’s tools appear in the list
MCP Server tools available after successful authentication

MCP Server tools available after authentication

  1. You can revoke authorization at any time:
TrueFoundry Gateway Dashboard showing how to revoke OAuth2 authorization for an MCP Server

Revoke your OAuth2 authorization

The Gateway passes the user’s JWT directly to the MCP server without transformation. The MCP server validates the token itself.Configuration:
  1. Register the MCP server with Token Passthrough authentication type
  2. Configure an External Identity to allow your IdP tokens
  3. The user’s JWT is automatically forwarded to the MCP server
With Token Passthrough, the MCP server is responsible for validating the token. Make sure the MCP server is configured to trust your IdP.
Unified Token Management: The AI Gateway stores and manages OAuth tokens for all MCP servers on behalf of each user. It maintains a mapping from user tokens to OAuth tokens for different MCP servers and automatically refreshes them when they expire. Users interact with the Gateway using a single token without managing multiple credentials.

Layer 4: Passing Custom Headers

You can pass custom headers to MCP servers using the x-tfy-mcp-headers header. This is useful for authentication tokens, metadata, or any headers your MCP server requires.
Format varies by API: The x-tfy-mcp-headers header format differs between MCP Gateway and Agent API:
  • MCP Gateway (this section): Uses different formats for remote vs virtual servers
  • Agent API: Always uses full FQN-based format (see Agent API docs)
import json
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

# Pass headers for a remote MCP server (flat structure)
headers = json.dumps({"Authorization": "Bearer your-token"})

transport = StreamableHttpTransport(
    url="https://{controlPlaneURL}/mcp/{groupName}/{mcpServerName}/server",
    headers={"x-tfy-mcp-headers": headers},
    auth="Bearer your-tfy-token"
)
For virtual MCP servers, use the remote MCP server identifier as the key (e.g., sample-mcp-group/server-1). Copy the identifier from the UI since virtual MCP servers contain multiple remote MCP servers.
Custom headers always override the default authentication configured for the MCP server.

Authentication Scenarios

The following scenarios show how different authentication flows work in practice. Each scenario includes a sequence diagram and a detailed step-by-step breakdown.

Scenario 1: TrueFoundry Users with OAuth-Based MCP Servers

Use case: Internal developers with TrueFoundry accounts accessing OAuth-protected services like Slack, GitHub, or Atlassian. This is the most common enterprise scenario where your developers authenticate to TrueFoundry and the Gateway handles OAuth token management for downstream MCP servers. Sequence Diagram for Truefoundry User accessing Oauth Based MCP Servers
StepActionDescription
1User → Control PlaneUser logs into TrueFoundry
2Control Plane → IdPTrueFoundry redirects to your identity provider (Okta, Azure AD, etc.)
3IdP → UserUser authenticates and receives IdP access token
4User → Control PlaneUser initiates OAuth flow for the MCP server (e.g., “Connect to Atlassian”)
5Control PlaneVerifies user has permission to access this MCP server
6Control Plane → External ProviderUser is redirected to the external service (e.g., Atlassian) to authorize access
7External Provider → Control PlaneExternal service returns OAuth tokens after user approval
8Control PlaneSecurely stores access and refresh tokens, linked to the user’s identity
StepActionDescription
1Agent → GatewayAI Agent sends request with TrueFoundry token
2GatewayValidates the TrueFoundry token
3GatewayChecks if the token has access to the requested MCP server/tool
4Gateway → Control Plane(If not cached) Retrieves user’s OAuth token for this MCP server
5GatewayCaches the OAuth token for subsequent requests
6Gateway → MCP ServerForwards request with the user’s OAuth token
7MCP Server → External ProviderValidates token and fetches user-specific data
8MCP Server → AgentReturns response through the Gateway
Key benefits of this flow:
  • Users authenticate once to TrueFoundry and access multiple OAuth-protected services
  • Tokens are automatically refreshed when they expire
  • Each user’s actions are attributed to their individual identity
  • Users can revoke access to specific services at any time

Scenario 2: End Customers with OAuth-Based MCP Servers (CIAM)

Use case: Your end customers (who don’t have TrueFoundry accounts) accessing OAuth-protected services through your application. This scenario is common for Customer Identity and Access Management (CIAM) where you want your customers to connect their own accounts (e.g., their Gmail, Slack, or CRM) to your AI-powered application. Sequence Diagram for End customers accessing Oauth Based MCP Servers
StepActionDescription
1User → IdPUser logs into your identity provider directly (not TrueFoundry)
2IdP → UserUser receives IdP access token
3User → Control PlaneUser initiates OAuth flow for the MCP server
4Control PlaneValidates the IdP token and extracts user identity
5Control PlaneChecks if the user/role has access to this MCP server
6Control Plane → External ProviderRedirects user to authorize access (3-legged OAuth)
7External Provider → Control PlaneReturns OAuth tokens; Control Plane stores them securely
StepActionDescription
1Agent → GatewayAI Agent sends request with IdP token (not TrueFoundry token)
2GatewayValidates the IdP token using your SSO configuration
3GatewayChecks if the extracted user identity has access to the MCP server/tool
4Gateway → Control Plane(If not cached) Retrieves the user’s OAuth token using their IdP identity
5GatewayCaches the OAuth token for performance
6Gateway → MCP ServerForwards request with user’s OAuth token
7MCP Server → External ProviderValidates and processes the request
8MCP Server → AgentReturns response through the Gateway
Key differences from Scenario 1:
  • Users authenticate with your IdP, not TrueFoundry
  • The Gateway validates your IdP tokens directly
  • Useful for B2B SaaS applications with end-customer integrations
You can also use this method for internal developers if you prefer not to use TrueFoundry tokens and want to leverage your existing identity infrastructure.

Scenario 3: Shared Service Account Authentication (Header-Based)

Use case: Accessing MCP servers with shared credentials where individual user identity at the downstream service is not required. This scenario is ideal for read-only access to shared resources, internal tools, or services that don’t support per-user OAuth. Sequence Diagram for Developers / End Customers accessing Bearer Token Based MCP servers
StepActionDescription
1Admin → Control PlaneAdministrator registers the MCP server with static header authentication
2AdminConfigures the shared API key or bearer token in the MCP server settings
3AdminDefines which users/roles have access to this MCP server through RBAC policies
The shared credentials are stored securely and never exposed to end users.
StepActionDescription
1Agent → GatewayAI Agent sends request with user’s TrueFoundry or IdP token
2GatewayValidates the user token
3GatewayChecks if the user has access to this MCP server (RBAC)
4GatewayInjects the shared credentials (static headers) into the request
5Gateway → MCP ServerForwards request with shared service account credentials
6MCP ServerProcesses request using the shared credentials
7MCP Server → AgentReturns response through the Gateway
When to use shared credentials:
  • Read-only access to knowledge bases or documentation
  • Internal analytics dashboards accessible by multiple teams
  • Legacy systems without OAuth support
  • Tools where actions don’t need individual user attribution
Security considerations:
  • All users share the same level of access to the downstream service
  • Actions cannot be attributed to individual users at the downstream service level
  • TrueFoundry’s audit logs still track which user made each request at the Gateway level

Scenario 4: Token Passthrough Authentication

Use case: Accessing MCP servers that validate tokens from your IdP directly, without TrueFoundry managing the authentication. This scenario is for organizations that want the MCP server itself to validate the user’s JWT rather than using OAuth2 token exchange.
StepActionDescription
1Configure External IdentitySet up SSO integration and External Identity as described in Layer 1
2Register MCP ServerRegister the MCP server with Token Passthrough authentication
3Configure MCP ServerEnsure the MCP server is configured to validate JWTs from your IdP
StepActionDescription
1User → Your IdPUser authenticates with your IdP and receives a JWT
2Agent → GatewayAI Agent sends request with user’s JWT
3GatewayValidates the JWT using External Identity configuration
4GatewayChecks if the user has access to this MCP server (RBAC)
5Gateway → MCP ServerForwards request with user’s JWT unchanged
6MCP ServerValidates the JWT against your IdP’s configuration
7MCP Server → AgentReturns response through the Gateway
When to use Token Passthrough:
  • Your MCP server already trusts your IdP
  • You want full control over authentication at the MCP server level
  • You don’t want TrueFoundry to manage OAuth tokens

Implementation Guide

This section provides practical code examples for implementing authentication in your AI agents.

Handling OAuth Flows in Code

When connecting to an OAuth2-protected MCP server, if the user hasn’t completed OAuth consent, the MCP Gateway returns an error containing the authorization URL. Your agent needs to extract this URL and redirect the user.
import re
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport


def get_auth_error_data(exception: Exception) -> str | None:
    """Traverse exception chain to find auth error with URL."""
    current = exception
    while current is not None:
        try:
            data = current.error.data
            if data and "Please visit:" in str(data):
                return str(data)
        except AttributeError:
            pass
        current = current.__cause__
    return None


def extract_auth_urls(error_data: str) -> list[str]:
    """Extract authorization URLs from MCP Gateway error."""
    match = re.search(r"Please visit:\s*(.+)$", error_data)
    if match:
        # URLs are separated by " , " (space-comma-space)
        return [url.strip() for url in match.group(1).split(" , ")]
    return []


async def call_mcp_with_oauth(
    mcp_url: str,
    auth_token: str,  # User's TrueFoundry PAT, Virtual Account token, or IdP JWT
    tool_name: str,
    tool_args: dict
):
    """Call an MCP tool, handling OAuth authorization if needed."""
    transport = StreamableHttpTransport(
        url=mcp_url,
        headers={"Authorization": f"Bearer {auth_token}"}
    )
    
    try:
        # Note: OAuth errors occur during connection, not tool calls
        async with Client(transport) as client:
            result = await client.call_tool(tool_name, tool_args)
            return {"success": True, "result": result}
            
    except Exception as e:
        error_data = get_auth_error_data(e)
        if error_data:
            auth_urls = extract_auth_urls(error_data)
            if auth_urls:
                return {
                    "success": False,
                    "auth_required": True,
                    "authorization_urls": auth_urls
                }
        raise


# Example usage
async def main():
    mcp_url = "https://<control-plane-url>/api/llm/mcp/<integration-id>/server"
    user_token = "user-tfy-token-or-idp-jwt"
    
    result = await call_mcp_with_oauth(
        mcp_url, 
        user_token, 
        "get_repositories", 
        {}
    )

    if result.get("auth_required"):
        # In a web app: redirect user to the authorization URL
        # In a CLI: print the URL for user to visit
        for url in result["authorization_urls"]:
            print(f"Please authorize access: {url}")
        
        # After user completes OAuth, retry the request
        # The MCP Gateway stores the OAuth token and future requests will succeed
    else:
        print(f"Success: {result['result']}")

Using Virtual Accounts for Server-to-Server Access

When your application needs to access MCP servers without individual user context:
import os
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

# Store Virtual Account token securely (e.g., environment variable)
VA_TOKEN = os.environ["VIRTUAL_ACCOUNT_TOKEN"]

async def call_mcp_tool(tool_name: str, tool_args: dict):
    """Call an MCP tool using Virtual Account credentials."""
    mcp_url = "https://<control-plane-url>/api/llm/mcp/<integration-id>/server"
    
    transport = StreamableHttpTransport(
        url=mcp_url,
        headers={"Authorization": f"Bearer {VA_TOKEN}"}
    )
    
    async with Client(transport) as client:
        result = await client.call_tool(tool_name, tool_args)
        return result

Token Passthrough Implementation

For MCP servers that validate tokens from your IdP:
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

async def call_passthrough_mcp(
    mcp_url: str,
    user_jwt: str,  # JWT from your IdP
    tool_name: str,
    tool_args: dict
):
    """Call an MCP tool with token passthrough."""
    transport = StreamableHttpTransport(
        url=mcp_url,
        headers={"Authorization": f"Bearer {user_jwt}"}
    )
    
    async with Client(transport) as client:
        result = await client.call_tool(tool_name, tool_args)
        return result
With Token Passthrough, the MCP server validates the token directly. Make sure the JWT is valid and has the required claims/scopes for the MCP server.

Choosing the Right Authentication Model

FactorPer-User OAuthShared Service AccountToken Passthrough
User attributionFull traceability to individual usersActions attributed to shared account onlyDepends on MCP server implementation
Access controlPer-user permissions at downstream serviceSame access for all authorized usersControlled by MCP server
Token managementGateway manages tokens per userSingle token managed by administratorsUser/application manages tokens
User experienceOne-time OAuth consent flowNo additional authorization requiredNo additional authorization required
Best forPersonal data, compliance-sensitive operationsShared resources, read-only accessCustom MCP servers with your IdP
ExamplesGmail, Slack, GitHub, AtlassianHugging Face, internal databases, knowledge basesInternal APIs, custom services

Decision Flowchart

Does the MCP server need per-user data from third-party services?
├── Yes → Use OAuth2 (Per-User Credentials)
│         └── Are users TrueFoundry platform users?
│             ├── Yes → Use TrueFoundry PAT
│             └── No → Set up External Identity

└── No → Does the MCP server validate tokens from your IdP?
         ├── Yes → Use Token Passthrough
         └── No → Does it require any auth?
                  ├── Yes → Use Static Header Auth (Shared Credentials)
                  └── No → Use No Auth
Most organizations use a hybrid approach: per-user OAuth for services with personal data (email, messaging, source control), shared credentials for internal tools and read-only resources, and token passthrough for custom internal APIs.

FAQ

Use this quick reference to decide between OAuth2 and Token Passthrough:
QuestionIf Yes →
Does the MCP server connect to third-party services (GitHub, Slack, Google, etc.)?OAuth2
Does the MCP server validate tokens from your IdP?Token Passthrough
OAuth2 is for when users need to authorize access to their accounts on external services. The Gateway manages the OAuth flow and stores tokens.Token Passthrough is for when you control both the identity provider and the MCP server, and want the MCP server to validate user JWTs directly.