The Microsoft Teams app provides read/write access to Microsoft Teams through the Microsoft Graph REST API (v1.0): teams and channels, channel messages and their reply threads, one-to-one and group chats, and online meetings with their transcripts, recordings and attendance reports. It can be consumed three ways: as a remote MCP server that Agent Factory agents call as tools, as a Builder app whose instructions you call directly from DSUL, and as a chat connector — an inbound Teams bot that hands each incoming message to your own automation. The MCP surface groups every operation into four entity tools (teams, channelMessages, chats, meetings), each driven by an action argument, and runs in the tenant app-instance context (it resolves the installing workspace’s own credentials). Authentication is per-user and supports several modes:
- Per-user OAuth2 (central client) (
oauthCentral, recommended): one Microsoft Entra OAuth Application is registered once by the platform maintainer; every end user signs in with their own Microsoft account. Nothing to register per tenant: each workspace just installs the app and clicks Connect. - Per-user OAuth2 (tenant client) (
oauth): paste your own Entra application (client) ID/secret in the connector config app. Each user signs in with their own account against your client (PKCE authorization-code flow). - Application (client credentials) (
clientCredentials): an Entra app with application Graph permissions and admin consent, acting without an interactive sign-in. Best for back-office / service automations and content indexing. - Direct access token (
accessToken): a caller-managed Microsoft Graph access token, used as-is with no exchange.
Conversations
Meetings & transcripts
Chat connector
Who is this for?
This connector is used by three different roles. Jump to the section that matches yours; each one is self-contained.Agent builder
Platform admin
Workspace builder
Prerequisites (Microsoft side)
- A Microsoft 365 tenant with Teams, and an Azure / Microsoft Entra ID tenant where you can register an application (or a maintainer who already did).
- An app registration in Microsoft Entra ID (Azure portal → App registrations), with a client secret created under Certificates & secrets.
- Microsoft Graph delegated permissions granted on the app (for the per-user OAuth modes), covering the resources you intend to use:
- Teams & channels:
Team.ReadBasic.All,Channel.ReadBasic.All,TeamMember.Read.All - Channel messages:
ChannelMessage.Read.All(addChannelMessage.Sendto post) - Chats:
Chat.Read,ChatMessage.Read(orChat.ReadWrite+ChatMessage.Sendto post) - Meetings:
Calendars.Read(meeting discovery goes through the calendar),OnlineMeetings.Read(orOnlineMeetings.ReadWrite),OnlineMeetingTranscript.Read.All,OnlineMeetingArtifact.Read.All - Sign-in / identity:
openid,profile,offline_access,User.Read
- Teams & channels:
- For the application (client-credentials) mode instead, grant the equivalent application permissions and have a Global Administrator grant admin consent. Reading channel messages with application permissions additionally requires Microsoft’s protected API approval.
- For the chat connector only: an Azure Bot resource with the Microsoft Teams channel enabled (see the Chat connector tab).
Platform admin (Governance): one-time platform setup
Platform admin (Governance): one-time platform setup
1. Configure the connector
Register the OAuth Application in Microsoft Entra ID
common / organizations for multi-tenant).Enter the credentials through the configuration app
microsoft-teams-next workspace and launch its Configuration app: <studio>/apps/microsoft-teams-next, also linked as Configuration app on the installed instance. Switch to the maintainer view and follow the in-app instructions to paste the Client ID, Client Secret, Tenant and (optionally) scopes; the app stores them in the core workspace’s secrets for you. Do not edit Studio’s raw Secrets by hand. These credentials stay in the microsoft-teams-next workspace and are never exposed to tenants or end users; token exchange is proxied through the core centralTokenExchange webhook so the client secret never leaves the core workspace.Tell workspaces to use the central client
oauthCentral in the connector configuration app (no client id/secret to enter on their side). Their users then just click Connect.2. Declare the capability in AI Governance
Generic connectors (broad tool surfaces meant to be shared across many agents, like Microsoft Teams) are best exposed as a named capability in AI Governance. Agent builders then enable that capability on their agents instead of pasting a raw MCP endpoint.Open AI Governance > Capabilities
Point it at the MCP endpoint
agent_id in the scope is what lets the connector identify and authorize the calling agent.Make it available to agent builders
Smoke-test
oauthCentral, trigger any tool. The user is prompted to connect once (Microsoft sign-in); subsequent calls reuse the stored token transparently and refresh it automatically.- Agent builder (Agent Factory)
- Workspace builder (DSUL)
- Chat connector (Teams bot)
Agent builder
Goal: let an agent you build in Agent Factory read Teams conversations, post messages, and pull meeting transcripts through MCP tools.agent_id that Agent Factory injects through the capability Scope, and that agent must appear in the connector’s authorized-agents allowlist (managed in the configuration app). The Microsoft Graph access token itself is resolved server-side from the configured auth mode.There are two ways to wire it up. Pick based on how much isolation you need.Option A: Enable the shared capability from the catalog
The fastest path: a Platform admin has already published a Microsoft Teams capability (see the Platform admin setup accordion above, §2), so you just pick it from the catalog. A workspace owner can publish it in one click with the config app’s Add to catalog button.Open your agent in Agent Factory
Add the Microsoft Teams capability
context_id,agent_id,user_id) are already wired by the admin: nothing to paste, and the shared instance accepts every agent, so there is no allowlist step on your side.Connect a Microsoft account (OAuth modes)
connect_url. Application (clientCredentials) and accessToken modes need no per-user sign-in.Option B: Run it from your own workspace (recommended)
For production agents, install the connector in your own workspace and point the agent at that workspace’s MCP endpoint.Install and configure the connector in your workspace
Allowlist your agent
Add the MCP capability to your agent
agent_id is what lets the connector identify and authorize your agent; without it, every call is rejected with an explicit “agent could not be identified” message. This Scope is separate from the Microsoft Graph OAuth scopes.Connect a Microsoft account (OAuth modes)
Brief the agent in its system prompt
Whichever option you pick, wiring the capability is not enough: the agent must know the MCP exists and when to use it. Copy-pasteable starter:agent_id.ChannelMessage.Send, Chat.ReadWrite, ChatMessage.Send and OnlineMeetings.ReadWrite. Any write attempt is then rejected by Microsoft Graph with 403 Forbidden, while the connection itself stays healthy because every connection check is a read.With the central client (oauthCentral) you do not create your own Entra app: you keep oauthCentral and simply enter the read-only scopes, which override the central default — provided the platform’s central app exposes those read permissions. The scope list is set at the workspace level (a workspace editor can widen it again); for a hard guarantee, back the connection with an Entra app limited to read permissions.Available Tools
Each tool takes anaction argument selecting the concrete operation, plus the per-action parameters.meetings list reads calendar events and resolve turns a joinUrl into the meetingId every other action needs. And a transcript is WebVTT text, not JSON: getTranscript returns speaker-tagged plain text, truncated on a line boundary (maxTranscriptCharacters, 20000 by default) so a long meeting cannot exhaust the agent’s context window.Output Formats
Every tool accepts anoutputFormat argument that controls the MCP response shape:verbose(default): a human-readable text view, optimized for LLM consumption.structured: concise machine-readable JSON instructuredContent.both: the structured payload, with its JSON also rendered as text.
Knowledge Resources
The connector also exposes Teams conversations as MCP Resources, so a knowledge base can index them. The tree is flattened to the discussion: a team and a channel are containers, and a thread — a root message plus its replies — is the document. Each thread’s revision folds in the timestamp of the newest reply and the reply count, because the root message’s ownlastModifiedDateTime does not move when someone answers; without that, an answered question would never be re-indexed. Access is checked per reader, at that reader’s own identity.Channel files are not indexed here: they live in the team’s SharePoint site and belong to the SharePoint connector.Tool Details
teams
list accepts no OData query option: Microsoft Graph answers 400 Query option 'Top' is not allowed on joinedTeams rather than ignoring it. It returns every team the identity belongs to in one response, so there is nothing to page.channelMessages
chats
meetings
list → resolve(joinUrl) → listTranscripts → getTranscript.Error Handling
Common Issues
“This agent is not authorized to use this connector”: The calling agent is not in the allowlist. Open the configuration app → Authorized agents → tick this agent (or enable Allow all agents) and Save. “The calling agent could not be identified”: The MCP capability Scope does not declareagent_id, so Agent Factory never injects the agent identity. Set the Scope to context_id,agent_id,user_id on the capability, then allow the agent in the config app.
“Microsoft Teams is not connected for this user”: No per-user OAuth token. Open the configuration app (OAuth mode) and click Connect, or use the agent’s connect flow.
“token refresh failed … must reconnect”: The stored refresh token was revoked or expired (Microsoft Entra invalidated it, or it aged past its limit). The connection is dropped automatically; the user must reconnect from the config app.
“OAuth is not configured”: Neither a tenant OAuth client nor the central platform client is available. Set the client ID/secret/tenant in the config app, or ask the platform maintainer to provision the central Entra OAuth client.
“Bot Framework credentials are not configured”: The bot app id or password is missing. Fill them in the configuration app’s Teams bot tab; do not set them from Studio’s Secrets screen.
The bot receives nothing: Check three things in order — the Microsoft Teams channel is enabled on the Azure Bot resource, the messaging endpoint matches the URL shown in the config app exactly, and the bot app is actually installed in the team or chat. A teams.bot.rejected event means the message arrived but failed verification, which is a credential mismatch rather than a wiring problem.
“Query option ‘Top’ is not allowed”: Some Teams collections reject OData options outright instead of ignoring them. listJoinedTeams returns every team in one response; do not pass top or a paging cursor to it.
A meeting cannot be found: There is no “list my online meetings” endpoint in Graph. Discover meetings with listMeetingEvents (the calendar), then turn the event’s joinUrl into a meeting with resolveOnlineMeeting.
Application mode cannot read channel messages: Reading Teams messages with application permissions requires Microsoft’s protected API approval on top of admin consent. Per-user OAuth is not subject to it.
Microsoft Entra redirect URI rejected: Entra rejects a colon in the redirect URI path. Register the redirect URI with the workspace’s raw id (/workspaces/<workspace-id>/webhooks/oauthCallback), not the slug: form; copy the exact value from the config app.