Teams MCP - Authentication

5 min read

Overview

The Teams MCP Server requires a Microsoft Entra ID (formerly Azure AD) app registration with delegated permissions to access Microsoft Graph API on behalf of users.

How the app registration is provisioned depends on your deployment model:

  • Unique SaaS — Unique provisions and manages the registration; you grant admin consent

  • Self-Hosted — your organization provisions the registration, manages secrets, and operates the server

For technical details about the OAuth flow, see Microsoft OAuth Setup Flow and FAQ - Why do I need a client ID and client secret?.

Required Permissions

All permissions are delegated — they act on behalf of the signed-in user. Identity and Teams messaging scopes only; ChannelMessage.Read.All is the one that requires admin consent.

Permission

Type

Admin Consent

User.Read

Delegated

No

offline_access

Delegated

No

ChannelMessage.Send

Delegated

No

ChatMessage.Send

Delegated

No

Chat.ReadBasic

Delegated

No

Chat.Read

Delegated

No

Team.ReadBasic.All

Delegated

No

Channel.ReadBasic.All

Delegated

No

ChannelMessage.Read.All

Delegated

Yes

No calendar, meeting, transcript, or recording scope is requested. For full justifications, see Microsoft Graph Permissions.

Transcript capture adds four scopes

A deployment with UNIQUE_INTEGRATION=enabled additionally requests Calendars.Read, OnlineMeetings.Read, OnlineMeetingTranscript.Read.All, and OnlineMeetingRecording.Read.All, the last two of which require admin consent. Only enable that mode if you intend to store meeting content in the Unique knowledge base — see Recordings & Transcripts.

Ingestion-only omits the messaging scopes

The messaging scopes above are requested only when CHAT_INTEGRATION=enabled (the default). Setting CHAT_INTEGRATION=disabled together with UNIQUE_INTEGRATION=enabled yields an ingestion-only deployment whose app registration requests only the identity and transcript scopes — none of the chat/messaging permissions. See Configuration — Chat Integration.

Unique SaaS

Recommended for most clients. When Unique runs Teams MCP, Unique provisions the Entra ID app registration for you. You only need to grant admin consent:

none
https://login.microsoftonline.com/organizations/v2.0/adminconsent?client_id=7c4f0aab-b24e-48c4-9b2d-d1c22dfdf99f&scope=https://graph.microsoft.com/.default&redirect_uri=https%3A%2F%2Fwww.unique.ai%2Fsetup%2Fconsent-completed%2Fentra-id

After approving, you are redirected to a Unique confirmation page.

The consent prompt lists the Required Permissions above, of which ChannelMessage.Read.All is the one that needs admin consent. Without it, users will see an error when trying to connect.

If your organization uses multiple Azure tenants, confirm you are granting consent for the correct directory. See Grant tenant-wide admin consent to an application for a tenant-specific admin consent URL; use application (client) ID .

Transcript capture uses a different app registration

The URL above consents to the chat-only app. A deployment with UNIQUE_INTEGRATION=enabled runs on its own app registration, which additionally requests the meeting-content scopes — grant consent for it with the URL in Recordings & Transcripts — Grant admin consent.

Self-Hosted

When your organization hosts Teams MCP, your team manages the full setup: Entra app registration, redirect URIs, secret management, and server configuration.

App Registration

hcl
module "teams_mcp_app" {
  source = "./deploy/terraform/azure/teams-mcp-entra-application"

  display_name     = "Teams MCP Server"
  sign_in_audience = "AzureADMyOrg"  # Single tenant
  notes              = "MCP server for Teams chats and channels"
  unique_integration = "disabled" # chat-only: omits calendar/meeting/transcript scopes

  redirect_uris = [
    "https://teams.mcp.example.com/auth/callback"
  ]

  confidential_clients = {
    production = {
      client_secret = {
        key_vault_id     = azurerm_key_vault.main.id
        end_date         = "2026-01-01T00:00:00Z"
        rotation_counter = 1
      }
    }
  }
}

Option 2: Azure Portal (Manual)

  1. Go to Azure PortalAzure Active DirectoryApp registrationsNew registration: - Name: Teams MCP Server - Supported account types: Accounts in this organizational directory only - Redirect URI: Web — https://teams.mcp.example.com/auth/callback

  2. Go to API permissionsAdd a permissionMicrosoft GraphDelegated permissions: - Add all permissions listed under Required Permissions

  3. Click Grant admin consent for [Tenant] and confirm. Chat-only deployments only need admin consent for ChannelMessage.Read.All. With transcript capture enabled, OnlineMeetingRecording.Read.All and OnlineMeetingTranscript.Read.All need it too.

  4. Go to Certificates & secretsNew client secret: - Set description and expiration - Copy the secret value immediately (shown only once)

  5. Go to Overview and note the Application (client) ID and Directory (tenant) ID

Redirect URI Configuration

The redirect URI must match exactly what's configured in the app registration:

none
https://<your-domain>/auth/callback

Examples:

  • Production: https://teams.mcp.example.com/auth/callback

  • Development: http://localhost:<port>/auth/callback

Multiple redirect URIs can be configured for different environments.

Tenant Configuration

For enterprise deployments within one organization:

Setting

Value

Azure Portal → "Supported account types"

Accounts in this organizational directory only

Terraform sign_in_audience

"AzureADMyOrg"

Multi-Tenant

For SaaS deployments serving users from multiple Microsoft 365 organizations:

Setting

Value

Azure Portal → "Supported account types"

Accounts in any organizational directory

Terraform sign_in_audience

"AzureADMultipleOrgs"

How it works: One app registration serves all tenants. When each organization's admin grants consent, Microsoft creates an Enterprise Application in their tenant. Users then authenticate via that Enterprise Application.

Considerations:

  • Data isolation: All tenant data stored in the same database (with tenant-scoped access controls)

  • Enterprise Application management: Each tenant admin controls user assignment and access

  • Compliance: Some organizations may require dedicated infrastructure for data residency

See Authentication Architecture - Single App Registration Architecture for details.

Secret Management

Client Secret

Best practices:

  1. Set appropriate expiration — balance security vs. operational overhead

  2. Rotate before expiration — create the new secret before the old one expires

  3. Use Key Vault — store secrets in Azure Key Vault, not directly in Kubernetes

  4. Monitor expiration — set up alerts for upcoming secret expiration

Rotation process:

  1. Create new client secret in Entra app registration

  2. Update Kubernetes secret with new value

  3. Restart pods to pick up new secret

  4. Verify authentication works

  5. Delete old client secret from Entra

Webhook Secret

The MICROSOFT_WEBHOOK_SECRET validates incoming webhook notifications from Microsoft Graph. It is only needed with transcript capture enabled; a chat-only deployment receives no webhooks.

  • Length: 128 characters (recommended)

  • Format: Random alphanumeric string

  • Generation: openssl rand -hex 64

This secret is passed to Microsoft when creating Graph subscriptions and returned in webhook payloads for validation.

This is standard Microsoft behavior, not Teams MCP specific. All Microsoft 365 apps use the same consent model.

Because admin-consent scopes depend on deployment mode (ChannelMessage.Read.All always; plus OnlineMeetingRecording.Read.All and OnlineMeetingTranscript.Read.All when transcript capture is enabled), the consent sequence is:

  1. Admin grants consent for the admin-required permissions for your mode (organisation-wide or per-user). Remaining permissions — including other chat scopes (ChannelMessage.Send, ChatMessage.Send, Chat.ReadBasic, Chat.Read, Team.ReadBasic.All, Channel.ReadBasic.All) — are user-consentable and do not require admin action.

  2. User consent — on first connection, the user sees the Microsoft consent screen and approves the remaining permissions

How to grant admin consent:

  1. Azure Portal → App Registration → API permissions

  2. Click "Grant admin consent for [Your Organization]"

  3. Or use the admin consent workflow for per-user approval

User Reconnection Experience (The "Login Flicker"):

After first connection, subsequent reconnections show a quick "flicker" (brief redirect sequence). This is normal — Microsoft validates the existing session through rapid OAuth redirects. See FAQ - Login "Flicker" for details.

For troubleshooting consent issues, see FAQ - Authentication & Permissions.

Microsoft Documentation

App Registration

Reference

Last updated