Azure MCP Server runs in two transport modes — stdio (local) and HTTP (remote) — each with a different authentication model.
| Stdio (local) | HTTP (remote) | |
|---|---|---|
| Who authenticates to Azure? | The server itself, using your developer credentials | Depends on the outgoing auth strategy (see below) |
| Inbound auth required? | No — communication is over local process pipes | Yes — Entra ID bearer tokens protect every request |
| Typical use | IDE extensions, CLI, local agents | Cloud-hosted server shared by multiple clients/agents |
When the server runs locally (the default), it authenticates directly to Azure services using credentials available on your machine.
The server uses a chain of credential providers. The first one that succeeds is used:
flowchart TD
Start{"Broker mode?"} -- yes --> Broker["OS broker (WAM on Windows)"]
Start -- no --> Env["EnvironmentCredential"]
Env -- fail --> VS["VisualStudioCredential"]
VS -- fail --> VSCode["VisualStudioCodeCredential"]
VSCode -- fail --> CLI["AzureCliCredential"]
CLI -- fail --> PS["AzurePowerShellCredential"]
PS -- fail --> AZD["AzureDeveloperCliCredential"]
AZD -- fail --> Browser["InteractiveBrowserCredential"]
Browser -- fail --> Failed(["Authentication failed"])
Broker --> OK(["Authenticated"])
Env -- ok --> OK
VS -- ok --> OK
VSCode -- ok --> OK
CLI -- ok --> OK
PS -- ok --> OK
AZD -- ok --> OK
Browser -- ok --> OK
Note
You can skip the chain and pin a specific credential by setting the AZURE_TOKEN_CREDENTIALS environment variable to the credential name. For example, to use only Azure CLI: AZURE_TOKEN_CREDENTIALS=AzureCliCredential.
Tip
In VS Code, run Azure: Sign In from the Command Palette (ctrl+shift+p) to authenticate quickly.
Set AZURE_MCP_ONLY_USE_BROKER_CREDENTIAL=true to skip the chain entirely and use the OS authentication broker (Web Account Manager on Windows). On unsupported operating systems it falls back to browser-based login.
Regardless of which credential is used, the authenticated identity must have the appropriate Azure RBAC roles on the target resources (for example, Storage Blob Data Reader for storage operations). See What is Azure RBAC? for details. For User-Assigned Managed Identity, also set AZURE_CLIENT_ID to the managed identity's client ID. If unset, System-Assigned Managed Identity is used.
| Environment | Recommended setup |
|---|---|
| Local development | Sign in with az login, VS Code Azure extension, or Azure PowerShell. The chain picks it up automatically. |
| CI / CD pipelines | Set AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID environment variables (service principal). |
| Production (hosted) | HTTP transport is recommended for production hosting — see Remote Authentication (HTTP Transport). If STDIO is required, set AZURE_TOKEN_CREDENTIALS=prod to restrict the chain to Environment, Workload Identity, and Managed Identity credentials only — no interactive browser fallback. |
When the Azure MCP Server is hosted remotely (for example, on Azure Container Apps) using HTTP transport, authentication operates in two layers:
- Inbound authentication — the client authenticates to the Azure MCP Server (protocol-hardened in MCP 2026-07-28)
- Outbound authentication — the Azure MCP Server authenticates to downstream Azure services and external MCP servers (see External MCP Server OAuth Compliance for registry server requirements under MCP 2026-07-28)
sequenceDiagram
participant Client
participant AzureMCPServer as Azure MCP Server
participant Entra as Entra ID
participant Azure as Azure Services
Client->>Entra: 1. Obtain bearer token
Client->>AzureMCPServer: 2. Call MCP Server with bearer token
AzureMCPServer->>Entra: 3. Validate inbound token
AzureMCPServer->>Entra: 4. Obtain outbound token
AzureMCPServer->>Azure: 5. Call Azure service with outbound token
Note
MCP 2026-07-28 changes: Inbound authentication validates JWT issuer, audience, and scope via Microsoft.Identity.Web. For registry-backed external MCP servers, HTTPS and non-empty scope entries are enforced by the server; issuer/audience validation of the outbound Azure Identity token is performed by the downstream resource. See External MCP Server OAuth Compliance for details.
Tip
Want to get started quickly? The azd templates below automate the entire setup illustrated above.
Every incoming request must carry a valid Entra ID bearer token with the required claims in the Authorization header. The inbound token can be obtained in one of two ways depending on the OAuth flow the client uses:
| OAuth Flow | Inbound Authentication | Required Claim |
|---|---|---|
| Authorization Code | Delegated — a user signs in and obtains a bearer token | Mcp.Tools.ReadWrite scope |
| Client Credentials | Application — an application obtains a bearer token (no user involved) | Mcp.Tools.ReadWrite.All role |
Note
The inbound authentication is determined entirely by the OAuth flow the client uses — the Azure MCP Server validates the incoming token and required claim but does not control how it is obtained.
The --outgoing-auth-strategy flag (UseOnBehalfOf or UseHostingEnvironmentIdentity) is passed when starting the Azure MCP Server and controls how it obtains outbound tokens to access downstream Azure services:
| Outbound Authentication | Behavior |
|---|---|
On-Behalf-Of (UseOnBehalfOf) |
Azure MCP Server exchanges the inbound user bearer token for a new token to access the downstream service |
Hosting Environment Identity (UseHostingEnvironmentIdentity) |
Azure MCP Server uses the hosting environment identity (typically a Managed Identity) to obtain a token to access the downstream service |
Note
If --outgoing-auth-strategy is not specified, the server defaults to On-Behalf-Of .
Use the following to verify your chosen inbound and outbound combination is supported:
| Inbound Authentication | Outbound Authentication | Supported |
|---|---|---|
| Delegated | On-Behalf-Of | ✅ |
| Delegated | Hosting Environment Identity | ✅ |
| Application | Hosting Environment Identity | ✅ |
| Application | On-Behalf-Of | ❌ Application bearer token carries no user identity, so there is nothing to exchange in an On-Behalf-Of flow |
The right strategy depends on your security, auditing, and deployment requirements:
| On-Behalf-Of | Hosting Environment Identity | |
|---|---|---|
| Per-user RBAC | Yes | No — shared identity |
| Audit trail | Per-user | Server identity only |
| Inbound auth type | Delegated only | Delegated or Application |
| Setup complexity | Higher | Lower |
| Best for | Multi-tenant / enterprise / compliance-sensitive scenarios | Single-team or single-client-application scenarios |
Configuring Entra ID app registrations, scopes, roles, and hosting infrastructure manually is complex. The following Azure Developer CLI (azd) templates automate the entire setup including deploying Azure MCP Server to Azure Container Apps:
| Template | Outbound Strategy | Client (Agent) |
|---|---|---|
| azmcp-obo-template | On-Behalf-Of | Foundry Agent, Copilot Studio, C# Client |
| azmcp-foundry-aca-mi | Hosting Environment Identity | Foundry Agent |
Each azd template provisions:
- Entra ID app registration(s) with the correct scopes and roles
- Managed identity with appropriate RBAC assignments
- Azure Container App configured to run the Azure MCP Server with all required environment variables and server flags
When the Azure MCP Server acts as an MCP client to external, OAuth-protected MCP servers (configured via registry), it must comply with MCP 2026-07-28 authorization hardening rules.
External MCP servers configured in the registry with OAuthScopes must meet these requirements:
| Requirement | Details |
|---|---|
| HTTPS endpoint | All OAuth-protected registry servers must use HTTPS (https:// scheme) — enforced by the server |
| Non-empty scopes | All scopes in OAuthScopes must be non-empty strings — enforced by the server |
| Issuer validation | A deployment requirement: the server's issuer identity should be resolvable and validated by its OAuth provider. Azure Identity bearer tokens carry issuer/audience claims that the downstream resource validates; the Azure MCP registry client does not perform additional client-side issuer binding |
| Application type | A deployment requirement: registry servers should be registered as the correct OAuth application type (confidential vs public client) with their OAuth provider |
| Scope registration | A deployment requirement: all scopes in OAuthScopes should be registered with the OAuth provider |
| Protected resource metadata | Recommended: Publish .well-known/oauth-protected-resource metadata per RFC 9728 (OAuth 2.0 Protected Resource Metadata) |
Issue: MCP 2026-07-28 protocol specifies that token endpoint requests include a resource parameter (per RFC 8707, Resource Indicators for OAuth 2.0), but some OAuth providers (e.g., Entra ID) do not support this parameter.
Impact: Access tokens are currently obtained without the resource parameter. This may result in overly-broad token scope.
Workaround: Configure your OAuth provider to accept token requests from Azure MCP Server even without the resource parameter. This is a known limitation documented in modelcontextprotocol/csharp-sdk issue #939.
Recommended mitigation strategies:
- Use narrow OAuth scopes that limit token usage to specific resources
- Implement rate limiting or request signing to protect token endpoints
- Monitor token usage patterns for unexpected requests
- Follow OAuth provider guidance for handling requests without the resource parameter
When registering an external MCP server with OAuth scopes, ensure that:
- The server's URL matches its registered issuer identity
- The issuer is resolvable and publishes OpenID Connect metadata
- Your OAuth provider can validate the issuer claim in received tokens
Example registry entry for an OAuth-protected MCP server:
{
"servers": {
"external-secure-server": {
"url": "https://my-mcp-server.example.com",
"title": "External MCP Server",
"OAuthScopes": ["mcp:invoke"]
}
}
}In this example:
- URL and issuer match (
my-mcp-server.example.com) - OAuth scopes are explicit and minimal
- The server is registered in your OAuth provider as a resource/API
To verify compliance:
- Verify issuer resolution: Ensure the server's
.well-known/openid-configurationis reachable - Test token acquisition: Confirm tokens can be obtained with your configured scopes
- Test token usage: Verify that MCP requests succeed with acquired tokens
- Test scope validation: Confirm that requests with insufficient scopes are rejected
- Test issuer mismatch: Verify rejection when token issuer doesn't match server identity