> For the complete documentation index, see [llms.txt](https://docs.frends.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.frends.com/guides/ai-features/setting-up-entra-id-oauth-for-mcp-triggers.md).

# Setting up Entra ID OAuth for MCP Triggers

How to use your own IDM for authenticating MCP Tools from Frends.

Integrating Microsoft Entra ID with Frends MCP Triggers allows developers and automated systems to securely access MCP tools using their existing corporate identities. By leveraging OAuth 2.0 authentication, you can enable interactive clients such as Claude Code, VS Code, and the MCP Inspector to list and execute Frends Processes without compromising security. This guide outlines the necessary configurations within the Entra ID portal, the Frends platform, and various MCP clients to establish a robust authentication flow.

{% hint style="info" %}
OAuth authentication for MCP Triggers is available from Frends 6.3.1 onwards.
{% endhint %}

## Requirements

Before you begin the configuration process, ensure that your environment meets several foundational criteria to support OAuth authentication for MCP Triggers.

You must have a Frends Agent with the `Mcp.Enabled` setting set to true, which is the default for recent versions. A Process containing at least one MCP Trigger must be deployed to this Agent to provide tools for the clients to call. On the administrative side, you require permissions to create and modify application registrations in the Entra admin center (formerly Azure portal), as well as access to Microsoft Graph Explorer for advanced claims mapping. Finally, you should have the public HTTPS URL of your Frends Agent available, as this will serve as a unique identifier during the Entra ID (formerly Azure AD) setup.

## Entra ID Application Registration

The initial phase of the setup involves creating a dedicated app registration in the Entra admin center (formerly Azure portal), which can be found under the **Applications menu** by selecting **App registrations**. This registration acts as both the protected API and the public client for authentication. Throughout the Entra portal, you may see references to the platform as Azure Active Directory or Azure AD.

### Manifest Configuration

The application manifest must be updated to ensure that Entra ID generates access tokens that are compatible with Frends.

Within your app registration, navigate to the **Manage** menu and select **Manifest** to locate the `api` configuration block. You must set the `requestedAccessTokenVersion` to `2` to ensure that the token uses the modern v2.0 endpoint formats for issuers and audiences. Additionally, you should set `acceptMappedClaims` to `true`, which allows the application to emit the custom tool access claims required by Frends.

```
"api": { 
    "requestedAccessTokenVersion": 2,
    "acceptMappedClaims": true
}
```

In the legacy manifest editor these are top-level `accessTokenAcceptedVersion` and `acceptMappedClaims`.

### API Configuration

In the **Expose an API** section under the **Manage** menu, define your Application ID URI, the default `api://{client-id}` is fine, and add a new scope named `Mcp.Tools`. Ensure this scope is enabled and configured to allow consent from both admins and users.

The full scope clients request is `api://{client-id}/{scope-name}`. Requesting a scope under this URI is what makes Entra issue a token whose audience is your app; without an exposed scope there is nothing a client can request that targets the agent.

### Identifier URIs

Spec-compliant MCP clients require specific identifiers to validate the resource they are attempting to access.

In the **Manifest editor**, you must add your Frends Agent MCP URL to the `identifierUris` array alongside the default API URI. This ensures that clients like Claude Code can successfully request tokens for your specific Agent endpoint.

```
"identifierUris": [
    "api://{client-id}",
    "https://<your-tenant>-agent-prod.frendsapp.com:9993/mcp"
]
```

{% hint style="info" %}
Remember to replace the example Agent URL with your actual Agent URL, with `/mcp` endpoint at the end.
{% endhint %}

### Authentication

Moving to the **Authentication** section under the Manage menu, you should add the **Mobile and desktop applications platform**. This platform type is essential for supporting public client flows using authorization code with PKCE.

Within this platform, register the **redirect URIs** for your intended clients, such as `http://localhost/callback` for Claude Code and the standard Claude desktop callback URL.

| Client                              | Redirect URI                                                                                                                                               |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Claude Code                         | `http://localhost/callback` and `http://127.0.0.1/callback` (Entra ignores the port on loopback redirects; Claude Code uses an ephemeral port per session) |
| MCP Inspector                       | `http://localhost:6274/oauth/callback` and `http://localhost:6274/oauth/callback/debug`                                                                    |
| claude.ai / Claude Desktop / mobile | `https://claude.ai/api/mcp/auth_callback`                                                                                                                  |
| VS Code                             | none needed (uses its own first-party client)                                                                                                              |

Finally, ensure that the **Allow public client flows** option—previously labeled as **Treat application as a public client**—is set to **Yes**.

## Advanced Claims Mapping for Tool Access

Frends determines which tools a user can execute by inspecting the `mcp_tools` claim within the provided access token.

### Creating and Attaching the Policy

Because Entra ID does not support custom claims through the standard portal interface, you must use Microsoft Graph to configure the tool grant logic. You can use Graph Explorer with Cloud Application Admin permissions, or the Microsoft Graph API for this.

First, you need to create a claims mapping policy using a POST request. This policy should map a user attribute, such as `extensionAttribute1`, to a new JWT claim type named `mcp_tools`.

Call URL: `POST https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies`

```
{
  "displayName": "FrendsMcpTools",
  "isOrganizationDefault": false,
  "definition": [
    "{\"ClaimsMappingPolicy\":{\"Version\":1,\"IncludeBasicClaimSet\":\"true\",\"ClaimsSchema\":[{\"Source\":\"user\",\"ID\":\"extensionattribute1\",\"JwtClaimType\":\"mcp_tools\"}]}}"
  ]
}
```

Once the policy is created, you must retrieve the object ID of your application's service principal.

Call URL: `GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '{client-id}'`

{% hint style="info" %}
Remember to replace `{client-id}` with the actual client ID of your app registration.
{% endhint %}

Next, attach the policy to it using a reference link. This configuration ensures that whenever a user authenticates, Entra ID attempts to include the tool access information in the resulting token.

Call URL: `POST https://graph.microsoft.com/v1.0/servicePrincipals/{sp-object-id}/claimsMappingPolicies/$ref`

```
{ "@odata.id": "https://graph.microsoft.com/v1.0/policies/claimsMappingPolicies/{policy-id}" }
```

{% hint style="info" %}
Replace `{sp-object-id}` with the ID from the GET call, and `{policy-id}` with the response ID from first POST call.
{% endhint %}

### Assigning Tool Grants to Users

After the policy is active, you must specify which tools each user is allowed to access by updating their profile attributes. You can do this through Microsoft Graph API for cloud-only users, or through **Users** section in Entra admin center.

The goal for each method is to set the `extensionattribute1` value, or whichever user attribute was chosen in the policy, to contain the granted scope for that user.

Possible values for the attribute:

| **Value**     | **Meaning**                                 |
| ------------- | ------------------------------------------- |
| `*`           | All tools available in Frends.              |
| `my.tool`     | This specific tool.                         |
| `myprocess.*` | All tools under the `myprocess.` namespace. |

Each attribute can contain one value. To grant wider range of tools, using wildcards is recommended.

The attribute's value is compared against the `mcp_tools` claim from Frends. While the `mcp_tools` claim supports multiple values, matching it against the Entra user attribute can be done only for single value, thus this authentication method allows only one claim and grant at a time.

#### Grant through Entra admin center

From the **Users** section in the Entra admin center, you can set the value of the chosen extension attribute for each user. Navigate to **Users**, then **All users**, and select the specific user to modify their profile attributes.

#### Granting through Graph

You can also set the attribute values for cloud-only users through Graph API or Graph Explorer.

Call URL: `PATCH https://graph.microsoft.com/v1.0/users/{user-upn}`

```
{ "onPremisesExtensionAttributes": { "extensionAttribute1": "my.tool" } }
```

## Frends OAuth Application Configuration

Once the Entra ID setup is complete, you must register the new authentication provider within the Frends Portal to enable token validation.

### Provider Identity and Metadata

Registering the Entra ID application in Frends allows the platform to recognize and validate tokens issued by Entra ID.

Navigate to the **Administration > Oauth Applications** section and create a new OAuth application. The name can be anything descriptive, but you should enter the exact v2.0 issuer URL for your Entra tenant, which follows the pattern `https://login.microsoftonline.com/{tenant-id}/v2.0`. Tenant ID is the Tenant GUID from Entra admin center.

Provide the Client ID of your Entra ID app in the Audience field. It is critical to check the **Allow MCP Trigger access** box, as this activates the discovery metadata endpoint on your Frends Agents and allows them to accept tokens from this specific provider.

### Scope and Identity Mapping

Properly mapping the internal token fields for the OAuth application is necessary for the Agent to correctly process the authentication context.

You must set the Scope claim type to `scp` because Entra ID uses this specific field for delegated permissions.

If you wish to identify the specific user who triggered a Process in your execution logs, you can set the Name claim type to `preferred_username` (optional).

Finally, enter the full URI of your exposed scope, such as `api://{client-id}/Mcp.Tools`, in the Scopes field. This information is used to challenge clients and inform them which permissions they must request from Entra ID.

## Client Integration and Verification

The final step is to configure your MCP clients to point to the Frends Agent and use the Entra ID application for authentication.

### Configuring Interactive Clients

Each MCP client requires the Client ID of your Entra ID application to initiate the OAuth flow.

#### Claude Code

`{client-id}` is the only client-side setting. Scopes come from the agent's 401 challenge:

```
claude mcp add-json frends-agent '{"type":"http","url":"{mcp-url}","oauth":{"clientId":"{client-id}"}}'
```

Then `/mcp` → the server → Authenticate. Do not pin `callbackPort`; the default ephemeral port avoids collisions between sessions and Entra ignores loopback ports.

#### Claude.ai / Claude Desktop (custom connector)

The organization admin adds the connector by URL and enters `{client-id}` as the OAuth client ID. Leave the client secret empty.

#### VS Code

Add the MCP server by URL. VS Code authenticates through its built-in Microsoft provider. Pre-authorizing its client ID (section 1.5) skips the consent prompt.

#### MCP Inspector

Set *OAuth Client ID* to `{client-id}`. The scope is read from the discovery metadata or can be entered manually as `api://{client-id}/{scope-name}`.

### Validating the Authentication Flow

You can confirm that the integration is functioning correctly by inspecting the discovery metadata and the tokens issued to users.

By performing a GET request to the well-known OAuth resource endpoint on your Agent, you should see the Entra ID issuer listed under the supported authorization servers.

```
curl -i -X POST {mcp-url} -H "Content-Type: application/json" -d '{}'

curl {mcp-origin}/.well-known/oauth-protected-resource/{mcp-path}
```

Furthermore, you can capture an access token and paste it into a validation tool to verify that the `aud` claim matches your client ID and that the `mcp_tools` claim correctly reflects the user's permissions.

If you encounter errors such as `invalid_target`, double-check that the Agent URL is registered as an identifier URI in the Entra ID manifest.

### Troubleshooting <a href="#id-5-troubleshooting" id="id-5-troubleshooting"></a>

<table data-search="false"><thead><tr><th width="266">Symptom</th><th>Cause and fix</th></tr></thead><tbody><tr><td><code>AADSTS9010010</code> / <code>invalid_target</code> at sign-in</td><td>The client sent the RFC 8707 <code>resource</code> parameter and the MCP URL is not an identifier URI → section 1.3</td></tr><tr><td><code>AADSTS50146</code> at sign-in</td><td>Claims mapping policy attached but <code>acceptMappedClaims</code> not set → section 1.1</td></tr><tr><td>401 from the agent with a valid-looking token</td><td><code>iss</code>/<code>aud</code> mismatch: check the token at jwt.ms; <code>ver: 1.0</code> or <code>iss: sts.windows.net</code> means <code>requestedAccessTokenVersion</code> is missing → section 1.1. Domain-form Issuer in the Frends OAuth application also fails: it must be the GUID form</td></tr><tr><td>Sign-in succeeds but the tool list is empty</td><td>Either the token has no <code>mcp_tools</code> claim (section 1.6), or the scope gate fails: Scope claim type must be <code>scp</code> when Scopes is set → section 2</td></tr><tr><td>No <code>resource_metadata</code> in the 401 / metadata endpoint returns 404</td><td>No MCP-enabled OAuth application has reached the agent: check the checkbox in the portal and that the agent has received the configuration update</td></tr><tr><td>Browser shows an empty page on <code>localhost</code> after sign-in</td><td>Something else occupies the client's callback port; for Claude Code, remove any pinned <code>callbackPort</code> so it picks a free ephemeral port</td></tr><tr><td>Consent prompt loops or is denied</td><td>The scope's <em>Who can consent</em> is admin-only, or tenant policy blocks user consent → grant admin consent (section 1.5)</td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.frends.com/guides/ai-features/setting-up-entra-id-oauth-for-mcp-triggers.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
