> ## Documentation Index
> Fetch the complete documentation index at: https://www.truefoundry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Microsoft Entra app setup

> Set up Microsoft Entra for MCP: app registrations, scopes, client credentials, and Gateway callback URL.

Use this guide when you already have an MCP server and need to register it in Microsoft Entra (formerly Azure AD) so TrueFoundry (or other clients) can obtain tokens.

To **write** an OAuth MCP server and wire up JWT verification, see [Create an OAuth MCP Server with Azure Entra](/docs/ai-gateway/mcp/mcp-server-oauth-azure). After Entra is configured, [register the server in TrueFoundry](/docs/ai-gateway/mcp/mcp-server-oauth-azure#add-the-mcp-server-to-the-truefoundry-ai-gateway).

<Steps>
  <Step title="Create an App Registration for the MCP Server (Resource/API)">
    This app registration represents your MCP server as a protected resource. It will define what permissions (scopes) are available for your API.

    <Accordion title="Instructions to create the App Registration">
      1. Navigate to **Azure Portal** > **Microsoft Entra ID** > **App registrations**
      2. Click **New registration**
      3. Configure:
         * **Name**: `CalculatorMCPServer`
         * **Supported account types**: Choose based on your needs (typically "Accounts in this organizational directory only")
         * **Redirect URI**: Leave empty for now (this is the API, not the client)

      <img src="https://mintcdn.com/truefoundry/62IaXsiblF4PkZxX/images/azure-oauth-app-registration.png?fit=max&auto=format&n=62IaXsiblF4PkZxX&q=85&s=353c98bb6e1723c97e52ed043381f7a5" width="2258" height="1610" data-path="images/azure-oauth-app-registration.png" />

      4. Click **Register**
      5. Note down the following from the **Overview** page:
         * **Application (client) ID** - This will be used as part of your audience
         * **Directory (tenant) ID** - Your Azure AD tenant ID
    </Accordion>
  </Step>

  <Step title="Expose an API and Define Scopes">
    Now we'll configure the app registration to expose an API with custom scopes that clients can request.

    <Accordion title="Instructions to expose API and create scopes">
      1. In your **CalculatorMCPServer** app registration, go to **Expose an API**
      2. Click **Add** next to **Application ID URI**
         * Azure will suggest `api://{client-id}` - accept this or customize it
         * This URI becomes your **audience** value

      <img src="https://mintcdn.com/truefoundry/62IaXsiblF4PkZxX/images/azure-oauth-app-id-uri.png?fit=max&auto=format&n=62IaXsiblF4PkZxX&q=85&s=8a79fc977b9e73e0c79c89b27e6eda69" width="1501" height="709" data-path="images/azure-oauth-app-id-uri.png" />

      3. Click **Add a scope** to create custom scopes:
         * **Scope name**: `calculator.add`
         * **Who can consent**: Admins and users
         * **Admin consent display name**: Add numbers
         * **Admin consent description**: Allows the application to add numbers
         * **User consent display name**: Add numbers
         * **User consent description**: Allows the application to add numbers on your behalf
         * **State**: Enabled

      <img src="https://mintcdn.com/truefoundry/62IaXsiblF4PkZxX/images/azure-oauth-scope.png?fit=max&auto=format&n=62IaXsiblF4PkZxX&q=85&s=0c1d0537ffba619868433a347006aa75" width="586" height="615" data-path="images/azure-oauth-scope.png" />

      4. Click **Add scope**
      5. Repeat to add another scope:
         * **Scope name**: `calculator.subtract`
         * Configure similar display names and descriptions

      <img src="https://mintcdn.com/truefoundry/62IaXsiblF4PkZxX/images/azue-oauth-scope-2.png?fit=max&auto=format&n=62IaXsiblF4PkZxX&q=85&s=29c84323df830964cbcd2f35902742e0" width="1129" height="390" data-path="images/azue-oauth-scope-2.png" />

      <Note>
        Your full scope names will be in the format: `api://{client-id}/calculator.add` and `api://{client-id}/calculator.subtract`
      </Note>
    </Accordion>
  </Step>

  <Step title="Create a Client App Registration">
    This app registration represents the client application (user-facing or machine-to-machine) that will access your MCP server.

    <Accordion title="Instructions to create the client app">
      1. Navigate to **App registrations** > **New registration**

      2. Configure:
         * **Name**: `CalculatorMCPClient`
         * **Supported account types**: Same as your API app
         * **Redirect URI**:
           * Platform: **Web**
           * URI: `https://<your-tfy-control-plane-url>/api/svc/v1/llm-gateway/mcp-servers/oauth2/callback`

      3. Click **Register**

      4. Note the **Application (client) ID** - this is your OAuth **Client ID**

      5. Go to **Certificates & secrets**

      6. Click **New client secret**
         * **Description**: `MCP Client Secret`
         * **Expires**: Choose based on your security requirements

      <img src="https://mintcdn.com/truefoundry/62IaXsiblF4PkZxX/images/azure-oauth-secret.png?fit=max&auto=format&n=62IaXsiblF4PkZxX&q=85&s=3c9ba3c5f723d8421857056922d670a8" width="1500" height="649" data-path="images/azure-oauth-secret.png" />

      7. Click **Add**
      8. **Important**: Copy the **Value** immediately - this is your **Client Secret** (it won't be shown again)

      <Warning>
        Store the client secret securely. It cannot be retrieved after you leave this page.
      </Warning>

      9. Go to **Authentication**

      10. Under **Implicit grant and hybrid flows**, ensure:
          * **Access tokens** is checked (for user auth)
          * **ID tokens** is checked (for user auth)

      11. Under **Advanced settings** > **Allow public client flows**: Set to **No**
    </Accordion>
  </Step>

  <Step title="Grant API Permissions to the Client App">
    The client app needs permission to access the MCP server API. We'll grant the scopes we defined earlier.

    <Accordion title="Instructions to grant API permissions">
      1. In your **CalculatorMCPClient** app registration, go to **API permissions**
      2. Click **Add a permission**
      3. Go to **My APIs** tab
      4. Select **CalculatorMCPServer**

      <img src="https://mintcdn.com/truefoundry/62IaXsiblF4PkZxX/images/azure-oauth-api-permissions.png?fit=max&auto=format&n=62IaXsiblF4PkZxX&q=85&s=6cb09f6b388943bd4210ddb042c02201" width="1493" height="642" data-path="images/azure-oauth-api-permissions.png" />

      5. Select **Delegated permissions** (for user authentication)
      6. Check:
         * `calculator.add`
         * `calculator.subtract`

      **Screenshot placeholder: Select permissions dialog**

      7. Click **Add permissions**

      8. For machine-to-machine authentication, click **Add a permission** again

      9. Select **CalculatorMCPServer** from **My APIs**

      10. Select **Application permissions**

      11. Check the same scopes:
          * `calculator.add`
          * `calculator.subtract`

      12. Click **Add permissions**

      13. Confirm by clicking **Yes**

      <img src="https://mintcdn.com/truefoundry/62IaXsiblF4PkZxX/images/azure-oauth-permissions.png?fit=max&auto=format&n=62IaXsiblF4PkZxX&q=85&s=0c7c68ad52f0f648867261bdcacfd254" width="1499" height="645" data-path="images/azure-oauth-permissions.png" />

      <Note>
        "Grant admin consent" is required for the application permissions to work. Delegated permissions can work with or without admin consent depending on your tenant settings.
      </Note>
    </Accordion>
  </Step>

  <Step title="Collect Necessary Information">
    Gather all the configuration values needed for your MCP server and client applications.

    From your Azure tenant and app registrations, collect:

    | Variable            | Example Value                          | Where to Find                                            |
    | ------------------- | -------------------------------------- | -------------------------------------------------------- |
    | **TENANT\_ID**      | `12345678-1234-1234-1234-123456789abc` | App Registration > Overview                              |
    | **OAUTH\_AUDIENCE** | `9876543-5678-5678-5678-987654321def`  | CalculatorMCPServer > Overview > Application (client) ID |
    | **CLIENT\_ID**      | `abcdef12-3456-7890-abcd-ef1234567890` | CalculatorMCPClient > Overview > Application (client) ID |
    | **CLIENT\_SECRET**  | `secret_value_here`                    | CalculatorMCPClient > Certificates & secrets             |

    <Warning>
      **Important**: The `OAUTH_AUDIENCE` should be just the Application (client) ID of your **CalculatorMCPServer** (the API), NOT the full `api://` URI. Azure tokens contain only the client ID in the `aud` claim.

      Example: Use `15a6b7c9-1b09-4e1a-9f38-53db81e18b05` instead of `api://15a6b7c9-1b09-4e1a-9f38-53db81e18b05`
    </Warning>

    From these values, construct:

    **OAUTH\_ISSUER**: `https://login.microsoftonline.com/{TENANT_ID}/v2.0`

    **OAUTH\_WELL\_KNOWN\_URL**: `https://login.microsoftonline.com/{TENANT_ID}/v2.0/.well-known/openid-configuration`

    **OAUTH\_JWKS\_URI**: Access the well-known URL and find the `jwks_uri` value (typically: `https://login.microsoftonline.com/{TENANT_ID}/discovery/v2.0/keys`)

    **TOKEN\_ENDPOINT**: `https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token`

    **CUSTOM\_SCOPES** (for Gateway configuration):

    * `api://{API_CLIENT_ID}/calculator.add`
    * `api://{API_CLIENT_ID}/calculator.subtract`
    * `offline_access`

    <Note>
      These custom scopes won't appear in Azure's well-known endpoint. You'll need to manually enter them when configuring the MCP server in the TrueFoundry AI Gateway.
    </Note>
  </Step>
</Steps>

## FAQ

<Accordion title="What is Machine to Machine Authentication?">
  Machine to Machine Authentication is a type of authentication that allows a machine to authenticate to the MCP server without user interaction. For M2M authentication, you can use the OAuth2 Client Credentials grant type to obtain access tokens directly.
</Accordion>

<Accordion title="What are Application Permissions vs Delegated Permissions?">
  * **Delegated permissions**: Used when a user is present. The app acts on behalf of the signed-in user. These require user consent (or admin consent).
  * **Application permissions**: Used for machine-to-machine scenarios without a signed-in user. These always require admin consent.

  For the AI Gateway (user authentication), use delegated permissions. For direct API access (M2M), use application permissions.
</Accordion>

<Accordion title="Why use .default scope for client credentials?">
  When using client credentials flow, Azure Entra ID requires the `.default` scope format (`api://{client-id}/.default`). This requests all application permissions that have been pre-consented for your application. You cannot request individual scopes in client credentials flow.
</Accordion>

<Accordion title="Why doesn't Azure include custom scopes in the well-known endpoint?">
  Azure's `/.well-known/openid-configuration` endpoint only returns generic OpenID Connect scopes:

  * `openid`
  * `profile`
  * `email`
  * `offline_access`

  Custom API scopes (like `api://{client-id}/calculator.add`) are:

  1. **Defined per app registration** in the "Expose an API" section
  2. **Granted per client** in the "API permissions" section
  3. **Not discoverable** via the well-known endpoint

  This means you must **manually configure** custom scopes in the TrueFoundry AI Gateway when adding the MCP server. The AI Gateway cannot auto-discover them like it can with Okta's custom authorization servers.
</Accordion>

<Accordion title="What's the difference between Azure and Okta OAuth?">
  Key differences:

  | Aspect                      | Azure Entra ID                      | Okta                                      |
  | --------------------------- | ----------------------------------- | ----------------------------------------- |
  | **Scopes format**           | `api://{client-id}/scope-name`      | Custom scopes                             |
  | **Audience in token**       | Just the client ID                  | Full audience URI                         |
  | **Custom scopes discovery** | Manual configuration required       | Auto-discoverable                         |
  | **Well-known URL**          | `/.well-known/openid-configuration` | `/.well-known/oauth-authorization-server` |

  Both work with TrueFoundry AI Gateway, but Azure requires manually entering custom scopes in the AI Gateway configuration.
</Accordion>
